Press J to jump to the feed. Press question mark to learn the rest of the keyboard shortcuts
74
Archived

How to (and not to) give a talk on F# -- Or any other language for that matter

180 comments
71% Upvoted
This thread is archived
New comments cannot be posted and votes cannot be cast
level 1

Step 0: don't be Jon Harrop.

level 2
4 points · 8 years ago

lets be fair. I am not a fan of him but his books give a good presentation of languages (ocaml and F#).

Also it is his trash comment to other languages that makes people to manly prove the contrary. Without him, no one would explore the dark corner of programming languages.

It takes a bitch for a group to have common focus.

level 3

IME the reaction of other users to The Harrop adopting their language has ranged between "please go away" and "please die in a fire." That self-promoting douche is one of the worst things about OCaml -- even worse than its petulant refusal to do arithmetic -- and he's trying to do the same to F#.

level 2
1 point · 8 years ago

Step 1: ???

Step 2: Profit!

Alternate ending:

Step 2: Congratulations! You're not a douchebag!

level 1
27 points · 8 years ago

Any one doing a presentation about any Language should take a look at some of the talks from Simon Peyton-Jones (Haskell). This guy knows how his material and how to present it. He always finds the right level and examples for his audience.

Here is one of his talks

level 2
8 points · 8 years ago

First of all you need his enthusiasm...

level 2
7 points · 8 years ago

Then again, this talk is 80 minutes, and the article said that that's about the amount of time you need to present a language. The article was giving advice on what to do in a 20 minute talk.

level 2
[deleted]
1 point · 8 years ago

Any other talk by him that is filmed better? This one films the back of his head or filming him pointing instead of filming the code.

EDIT: n/m found slides in comments http://conferences.oreillynet.com/presentations/os2007/os_peytonjones.pdf

level 1
11 points · 8 years ago

DON'T use a demo based on a mathematical principle (like Fibonacci, factorial, or some other exponent-hugging formula). I ask you, how many developers find themselves writing that kind of code on a daily basis?

DO use a demo based on real-world environments or problems. Use domain types that could have come from a regular line-of-business scenario; my favorite is "Person" ...

I think this represents a cultural difference in the kind of code corporate/industrial/OO programmers vs. academic/functional programmers consider to be "typical". I know that my code --- even when it is not particularly "mathematical" --- far more resembles something like a factorial function than AddEmployeeToPayroll, and so I find the former sort of example much more compelling.

The take-away point is that it's a two-way street: possibly we (the strawman FP fanatics) tend to think your "Person" and "Employee" examples are irrelevant contrived simplistic B.S., merely ginned up to make OO-style programming look like it has enough nails to count as a good hammer, in the same way you don't see the relevance of our factorial examples.

level 2

academic/functional programmers consider to be "typical". I know that my code --- even when it is not particularly "mathematical" --- far more resembles something like a factorial function than AddEmployeeToPayroll, and so I find the former sort of example much more compelling.

You're already in the choir. There's no need to preach to you. If you're introducing F# to people unfamiliar with functional programming, then relevant examples for an existing functional programmer aren't very helpful.

level 3
4 points · 8 years ago

This is a completely fair point!

Let me confess further: when the article says it is about identifying "structural failures I've seen in several talks attempting to describe F# to the general .NET computing community" it is probably making good recommendations. I bet the general .NET computing community does want to hear "Person" and "Employee" examples.

But I've sat through talks that make the opposite mistake, too. That's all I'm trying to say; that there's some symmetry in the situation: one culture thinks the other culture's examples are "atypical" and weird, and vice-versa. I'm not substantially even disagreeing with the content of the original article.

level 4

But I've sat through talks that make the opposite mistake, too.

That's entirely valid. When I see academics saying, "What's so great about OOP, we don't get it?" and then you see some guy going "look, I can make objects for my Employees and Accounts!" there's the same disconnect.

An academic or theoretician doesn't care about the specific nouns you're embodying as much as they do the underlying properties of the language and its type system (at least as far as I can tell).

level 5
6 points · 8 years ago

Yes, exactly! Not that there aren't academics into OOP as well, but they're nearly as alien to me as industry OOP people.

The disconnect there is that they (at least the ones I talk to) talk about type systems still, so we have some language in common, but it feels like they believe subtyping is king, and you've got to have it, and it has to be all mixed up in every other feature of the type system.

And I ask, why, why is subtyping so important? I hardly ever feel like I need it in the kind of code I typically want to write. And they say, well, suppose you have Persons and Employees and Accounts...

level 6

And I ask, why, why is subtyping so important?

I think a big part of the answer is that compared to other ways of building abstractions and composite types (algebraic data types, etc.), subtyping is open-ended. You can build a library of base classes and thousand of users can all extend it easily with their own subtypes, which your library can still easily use.

That's super important in industry where you have large teams, a lot of code sharing, and code that gets used for years and years. Meanwhile, an academic who only works on relatively small programs by himself or with a few others doesn't understand the value of that open-ended-ness.

level 7
[deleted]
3 points · 8 years ago · edited 8 years ago

This is a good point. Interestingly, it's also where the soul-searching the statically-typed FPers have done has paid off the most, as you'll see if you google "expression problem."

level 7

This is the story I often hear, but subtyping is still not necessarily essential for all forms of "open-endedness" or "extensibility" or what-have-you.

You can build a library of types and higher-order functions, and thousands of users can all extend it easily by supplying their own functions, which your library can still easily call.

It's not that we academics can't imagine the usefulness of extensibility, and indeed when we collaborate in larger groups and write bigger programs (which we do sometimes, despite the stereotype --- take a look at the rich abstractions used in major compiler and logical frameworks projects) we make things extensible for certain values of extensible --- but not always through subtyping.

Look at emacs, for a non-academic, non-typed, but still FP example: it has hooks everywhere for extensibility. The places where extensibility happen are fairly well-controlled. Emacs's language happens to be a unityped lisp, and so doesn't make any substantial compile-time guarantees, but there's no reason why a type discipline can't describe this form of extensibility.

level 8

You can build a library of types and higher-order functions

That works too, but I think extensibility through HoF is finer-grained than most business apps would prefer. I think the typical entities a business application deals with are "bigger" than your average academic program, even a fairly large one. Maybe this is just the influence of OOP on thinking, but I tend to think in terms of "OK, I'm defining a new noun, and it has this entire set of capabilities it needs to support" and less "OK, can my new noun be used with this function and this one and this one?" The granularity seems to be a bit bigger, and I think subtyping lends itself to that more than HoFs.

(which we do sometimes, despite the stereotype --- take a look at the rich abstractions used in major compiler and logical frameworks projects)

Compilers certainly are non-trivial, but if you compare a typical enterprise app and the stack of libraries and frameworks it sits on, I think a compiler is still relatively small. It's even more true when you consider how many libraries and frameworks are shared across companies. Literally millions of people are using the Java collection APIs and the .NET base classes. Imagine if those libs were using discriminated unions. Adding a case to one of those unions would break millions of users' code.

Look at emacs, for a non-academic, non-typed, but still FP example: it has hooks everywhere for extensibility.

Emacs is another interesting example. You mention that it "happens" to be dynamically typed, but I think that's an absolute key ingredient in its extensibility. At the same time, it has a high cost. Emacs has a reputation for being slow, massive, and hard to learn. I'm not hating on it, but I don't think it's a great case study in the power of FP. If it was, why would so many newer editors have overtaken it? Why couldn't it keep up?

I do like FP, especially in multi-paradigm languages, but I hate the attitude many academics have that it's clearly superior to OOP and it just because industry programmers are too dumb to get it. Maybe OOP really is just a better fit for a lot of the programming being done outside of academia.

level 6
Original Poster1 point · 8 years ago

And I ask, why, why is subtyping so important?

GUIs. If you are building GUI frameworks then subtyping is incredibly important. But even there, composistion is still king.

level 7
[deleted]
4 points · 8 years ago

I'll respectfully disagree: FRP wins big with GUIs.

level 8
Original Poster2 points · 8 years ago

You are comparing apples with oranges. Subtyping is a way to define the controls in a window. Reactive programming is a way to alter the state of those controls. These techniques are quite compatible.

level 9
[deleted]
2 points · 8 years ago · edited 8 years ago

That's a fair point. Let's put it this way: in traditional GUI frameworks, you inevitably wind up dealing with two hierarchies: a subtyping/subclassing (most OO languages conflate the two) hierarchy expressing static kind-of relations among GUI elements, and a dynamic "containment" hierarchy expressing "handles" relations among events and their handlers. It's true that subtyping nicely captures, e.g. that a menu is a menu is a menu. Two observations:

  1. That doesn't necessarily imply objects (cf. conflating subtyping and subclassing).

  2. FRP addresses the relations between event streams and how they're handled far more effectively than objects.

So I think I'm agreeing with your major thesis while striving to distinguish between subclassing and subtyping on one hand, and kind-of and handles on the other.

level 10
Original Poster1 point · 8 years ago

That doesn't necessarily imply objects

What alternative do you prefer?

My favorite way of designing UI is currently declarative languages, especially XAML. That isn't exactly based on composition or subtyping, as it also heavily uses a form on inheritance closer to CSS than anything else I've encountered. But CSS is just styling, XAML uses it for darn near everything.

level 8
1 point · 8 years ago

Please can you elaborate and give references?

level 9
Original Poster1 point · 8 years ago

FRP or Functional Reactive Programming is just a subset of the broader Reactive Programming model. This has not gone unnoticed by .NET developers.

http://www.infoq.com/news/2009/07/Reactive-Framework-LINQ-Events

level 10
[deleted]
2 points · 8 years ago

That's right--someone else recently pointed me to Rx. Very nice! Thanks!

level 9
[deleted]
1 point · 8 years ago
level 2

I think the point is that when you ask a FP zealot to show you a cool functional program, they will show you factorial, or some other elegant trick.

But then when you ask them to show you a REAL program, you get a blank stare.

level 3
15 points · 8 years ago

Some real FP programs: CouchDB (Erlang); xmonad, gitit, and darcs (Haskell); and Unison (Ocaml), just to pick from each of a few major FP languages.

level 4
10 points · 8 years ago

You could add MLDonkey as another example of a large-scale OCaml program:

A lot of designers of functional languages have one dream: finding a killer application, outside of the world of symbolic programming ( compilers, theorem provers, DSLs ), that would make their language spread in the open-source community. One year ago, we tackled this problem, and decided to use Objective-Caml to program a network application in the emerging world of peer-to-peer systems. The result of our work, MLdonkey, has superseded our hopes: it is currently the most popular peer-to-peer file-sharing client on the well-known freshmeat.net site, with about 10,000 daily users. Moreover, MLdonkey is the only client able to connect to several peer-to-peer networks, to download and share files. It works as a daemon, running unattended on the computer, and can be controlled remotely using three different kind of interfaces. In this paper, we present the lessons we learnt from its design and implementation.

(Quoted from http://pauillac.inria.fr/~lefessan/papers/#icfp2003)

level 4
3 points · 8 years ago · edited 8 years ago

erlang: rabbitMQ, ejabberd, riak, scalaris

clojure:: incanter, leiningen

Scala: I don't know the landscape so well, but there must be something..

level 5

Twitter, LinkedIn, FourSquare and many more. It can be argued that they're not coded in a pure functional style, though

level 3
Comment deleted8 years ago
level 4
6 points · 8 years ago · edited 8 years ago

And the space between is taken by the multi-paradigm languages which are mostly imperative languages in disguise (Python, Ruby, Perl, PHP, etc.).

I think that there are plenty of multi-paradigm languages, like F# and the various Lisps and MLs, that are mostly functional languages in (possibly very loose) disguise; and plenty more that are neither fundamentally functional nor fundamentally imperative (Mozart, for example, which I think of as emphasising the dataflow programming paradigm).

EDIT: Sorry, I bracketed that, probably wrongly, as “(mostly imperative) languages in disguise” rather than “mostly (imperative languages in disguise)”.

level 3
5 points · 8 years ago

Well, it is talking about programs that can be described in the course of a talk. I'm not sure what you mean by "REAL" programs. The distinction the article is making seems to be between "demos based on mathematical principles" vs. "real-world problems".

The point I am making is that there do exist useful programs (say, compilers, financial analysis, graphics) that are based on (sometimes rather abstract) mathematical principles. It's more exciting to people who already are biased to like that sort of thing (for example, me) to see how programming languages can embody those mathematical principles.

Conversely, it's more exciting to people who don't like mathematical abstractions to see demos and examples that aren't so abstract. I'm not saying one audience is better than the other; I'm just saying that the "no factorial please" audience isn't everybody.

level 3

Right. These fp zealots using functional programming are all giving you a blank stare.

level 4
8 points · 8 years ago

The blank stare is because they're wondering how the mathematically-challenged person in front of them got past security.

level 5

When was the last time your superior mathematical genius got you through the airport?

level 6

Don't fight the stupids. They bring you down to their level and then beat you with experience.

level 3

..and you just demonstrated jcreed's point.

level 1
12 points · 8 years ago

Use of the terms "catamorphism" or "monad" or "partial application" or "currying" in your introductory talk is an exercise in stroking your own ego ….

Perhaps it's just a difference in comfort level (since I've used Perl a lot longer than I've used Haskell), but, to me, the concept of ‘currying’ (and, by loose analogy, therefore ‘partial application’) is much more mainstream than that of a catamorphism or a monad; and it's much more likely that a programmer, even one only loosely steeped in the functional yoga, will think “I need currying here” than “I need a catamorphism here” (unless he or she is a Squiggologist).

EDIT: Then again, I'm a mathematician, not a programmer, so what do I know?

level 2
2 points · 8 years ago

ObTwoProblemsJoke:

A programmer had a problem and thought "I know! I'll use currying!"...

level 3
3 points · 8 years ago

A programmer had a problem and thought "I know! I'll use currying!"...

… and then, instead of 2 problems, had a problem that output problems?

level 2

And there's the problem with languages like Haskell and F# (well, especially Haskell). You can't even understand the frikken "putStrLn" statement without talking about the MOST complicated feature of the language.

I consider it a design flaw, and went back to CL.

level 3
20 points · 8 years ago

I don't understand this (common) complaint. It seems to me like saying “I don't like to use C, because, just to use a simple string concatenation, I have to understand the assembly code to which it compiles.”

If you want to understand the theoretical underpinnings of monads, then they're there for you (which is more than many languages built on ad hoc semantics can say); if not, then you say

Prelude> putStrLn "Hello, world"

Hello, world

and Haskell will not give you a quiz about why that happened.

level 4
9 points · 8 years ago

It seems to me like saying “I don't like to use C, because, just to use a simple string concatenation, I have to understand the assembly code to which it compiles.”

I don't think that analogy quite works. The assembly C compiles down to is just an implementation detail; it could just as easily compile down to a completely different form, or be interpreted, or whatever. At least in theory, you can understand C perfectly without knowing anything about assembly. On the other hand, monads are part of the semantics of IO in Haskell. You may be able to blunder around without understanding them, but you'll never truly comprehend Haskell code.

level 5

I think a better point might be : "I don't like to use C, because, just to use a simple string concatenation, I have to understand pointers and memory".

And you clearly need to understand memory & pointers to make a "good" call to strcat without blowing anything.

level 5
15 points · 8 years ago · edited 8 years ago

This myth needs to be burned. Tell me what about the following Haskell code screams monads that the C# code does not:

--HASKELL

main = do putStrLn "What is your name?" name <- getLine

putStrLn ("What is your favorite file,  " ++ name ++ "?")
path <- getLine
text <- readFile path

putStrLn "The contents of your favorite file are:"
putStrLn text

//C#

using System;

using System.IO;

public static void Main()

{ Console.WriteLine("What is your name?"); string name = Console.ReadLine();

Console.WriteLine("What is your favorite file, " + name + "?");
string path = Console.ReadLine();
string text = File.ReadAllText(path);

Console.WriteLine("The contents of your favorite file are:");
Console.WriteLine(text);

}

It doesn't matter that Haskell uses monads for IO, or that C# uses unnamed feature X for IO. The user is pretty blind to both of these facts.

Edit: Code formatting

level 6
12 points · 8 years ago · edited 8 years ago

Your extremely simple examples look similar, but they're not, and that would become apparent in even slightly more complex code. How would you explain why you need else return () after if statements with no other else clause in IO code without explaining monads? How would you explain why putting a return statement in the middle of an IO function doesn't make it return early, or seemingly have any effect at all? How would you explain the <- operator, and how it can shadow names but not rebind them? Etc.

Edit: Actually, a simpler and probably more common example: How would you explain why if you want to return the result of an IO function foo, you just put foo args... inside your do statement, but if foo isn't an IO function, you need to use return $ foo args...?

level 7
3 points · 8 years ago

The way I explain this to newbies is that IO represents a contamination of your program. Therefore values retrieved from or written to IO, need to have an IO wrapper around them. This is just the same as when learning Java that primitive types need to be put in a wrapper object in order to be used in an array. Though Java has changed this since, the concept of wrappers is ubiquitous in programming. Understanding a wrapper is a very separate concept from understanding a monad.

From my personal experience when first learning Haskell, I didn't learn how monads worked until 3 months later (I only taught myself concepts as they became necessary). I did however know how to write IO, return statements and all, from the first few days.

Finally, code in IO that is too much more complicated than what I wrote above is many times a code smell in Haskell, which emphasizes keeping logic out of IO. For the project I am currently working on, a clone of the GNU coreutils in Haskell, I've never written any code in IO more complex than what I gave above.

level 8
2 points · 8 years ago

If I were a Haskell newbie and someone explained IO to me that way, I would ask, "Ok, so what function do I call to unwrap an IO object?" And of course, the answer is, "You can't, not directly." Once you've explained why not, and what can be done instead, you've pretty much explained monads.

level 9
6 points · 8 years ago

No, I just say that you can only unwrap IO in a do block. No additional explanation needed, and it has gone over well with those I've taught. This forces people to think about how they use IO, which is a necessary part of learning Haskell, I admit without regret, as it's a good thing. But still, I haven't so much as mentioned the M word to one person I am teaching, and as a result, she's had no problems learning IO.

I'll acknowledge that most beginner Haskell tutorials out there are foolish for mentioning monads at all. It is a sad state of affairs. This is why "Learn You A Haskell" is the best Haskell tutorial: it doesn't cover monads at all (it might have had some passing references to them, I don't recall).

level 10

Well, "wrapped value which can only be unwrapped inside of a do block" is semi-close to the definition of a monad in Haskell, isn't it? Obviously, >>= is more fundamental than do blocks, but do blocks can accomplish the same things, and have the same semantics.

level 9
1 point · 8 years ago · edited 8 years ago

That's incorrect. The one-way property of IO values is a special property of the IO monad. Most monads are not like that.

Edit: Late to this party.

level 7

Those are real cases that a new Haskell programmer will encounter, sure. But are they really that complicated? Sure, it's different from C, but it's not terribly hard to understand if you're willing to try.

I find the biggest misconception about Haskell is that you have to be a category theorist to use the language reasonably well. I couldn't tell you what the heck a zygomorphism is. But I get monadic IO; immutable let bindings don't freak me out; I'm not afraid of if expressions that require a balancing else; and I'm not terrified that return has an unexpected meaning. It didn't take me long to get that far, and I don't think I'm overly smart, so I suspect many others could get that far too (with a little patience).

level 8

I couldn't tell you what the heck a zygomorphism is.

Sexual intercourse.

level 9

So what's an anamorphism?

level 10

My dictionary says:

from Greek anamorphōsis ‘transformation,’ from ana- ‘back, again’ + morphosis ‘a shaping’

so I'm guessing buttseks.

level 8
4 points · 8 years ago

Those are real cases that a new Haskell programmer will encounter, sure. But are they really that complicated? Sure, it's different from C, but it's not terribly hard to understand if you're willing to try.

Right, I agree; it's not very hard to understand how those cases work. However, understanding them implies understanding monads -- maybe not in a crazy mathematical category theory way, but at least in terms of what their basic operations are in Haskell, and how those apply to IO.

level 9
15 points · 8 years ago

There are gazillions more weird and unusual things in a language like C, the difference being that there is no underlying theory to "understand" other than "this is the way it is". The fact that you can understand Haskell's IO in terms of a more principled structure is a good thing, not a bad thing. If you don't want to, you don't have to, you can just accept it as "the way it is", just like you have to for every idiosyncratic part of C.

level 10
2 points · 8 years ago

I'd turn that around and say that C has the advantage. It's (nearly) complete in itself, and if you want to dig deeper it's not hard to see how C maps to the hardware, and that's it, that's the world. From there you can build up to C++ or C# and see how they work.

Haskell doesn't have that. Understanding Haskell, how it's put together, why it works the way it does, requires learning a theory external to the language; digging into the implementation of putStr is impossible, Haskell has no way to express it.

level 9

Right, I agree; it's not very hard to understand how those cases work. However, understanding them implies understanding monads -- maybe not in a crazy mathematical category theory way, but at least in terms of what their basic operations are in Haskell, and how those apply to IO.

Certainly, I agree with you there, and there is definitely a greater learning curve to do IO in Haskell than in others languages I've used.

level 5
5 points · 8 years ago

You don't have to understand monads to write IO in Haskell. If you want to write your own monads you obviously do, just like if you would have to write some inline assembly to do various things in C. Eventually you should probably make the effort to understand monads, but to say that you can't understand "putStrLn" to a working level without knowing how it's implemented is simply false.

level 5

Since Haskell has monadic do-notation, I think his analogy to C is spot-on.

level 6
3 points · 8 years ago

Do notation is syntactic sugar, not an abstraction, and it doesn't change the semantics of monads.

level 7

It enables you to avoid knowing what's happening in a monad since you don't have to chain lambdas manually. A monadic computation ends up looking like an imperative program, which is eminently understandable to most programmers.

level 4
3 points · 8 years ago

I'm not trying to speak for anyone else, but here's what happened when I tried to learn Haskell:

  1. Oh here is a tutorial. I will learn from it.

  2. Hmm this is interesting.

  3. Okay, the tutorial is interesting but now I am going to do something non-trivial.

  4. HALP WHAT IS GOING ON

  5. Screw Haskell

I mean 4. literally; I couldn't comprehend Haskell's model of computation. C, Java, Python, Ruby, etc all permit a mechanical model, with the IP and register dump and all that. You can understand code by constructing a CPU in your mind and running code through it. That doesn't work with Haskell.

Not to mention that it was nearly impossible for me to estimate the time or space complexity of the code I was writing.

level 5

Have you tried Real-World Haskell? That was the book that made the difference for me between your step (4) and “Hey, this is a beautiful language!” (Then again, I'm not sure that anything I've done with it counts as non-trivial.)

level 6
1 point · 8 years ago

I have tried it, and put it down around chapter 5. It's a good book, but I won't have time for it until maybe this summer.

level 3
Original Poster12 points · 8 years ago

You comment led me to actually look up putStrLn. This is what I read:

The question immediately arises: "how do you 'run' an action?". This is something that is left up to the compiler. You cannot actually run an action yourself; instead, a program is, itself, a single action that is run when the compiled program is executed. Thus, the compiler requires that the main function have type IO (), which means that it is an IO action that returns nothing. The compiled code then executes this action.

However, while you are not allowed to run actions yourself, you are allowed to combine actions. There are two ways to go about this. The one we will focus on in this chapter is the do notation, which provides a convenient means of putting actions together, and allows us to get useful things done in Haskell without having to understand what really happens. Lurking behind the do notation is the more explicit approach using the (>>=) operator, but we will not be ready to cover this until the chapter Understanding monads.

http://en.wikibooks.org/wiki/Haskell/Simple_input_and_output

Now translated into C:

The question immediately arises: "how do you 'run' a statement?". This is something that is left up to the compiler. You cannot actually run a statement yourself; instead, a program is, itself, a single statement that is run when the compiled program is executed. Thus, the compiler requires that the main function have type void, which means that it is a statement that returns nothing. The compiled code then executes this action.

However, while you are not allowed to run statements yourself, you are allowed to combine statements. There are two ways to go about this. The one we will focus on in this chapter is the semi-colon notation, which provides a convenient means of putting statements together, and allows us to get useful things done in C without having to understand what really happens. Lurking behind the * semi-colon* notation is assembly, but we will not be ready to cover this until the chapter Understanding calling conventions.

See? All you have to do is translate their mumbo-jumbo into the mumbo-jumbo we are already familiar with and it becomes quite approachable.

level 4

Now translated into C: ... Thus, the compiler requires that the main function have type void

AAHHH!!!!! ANATHEMA!!! main() does not return void; main returns an int! Failure to return a value from a non-void function leads to undefined behavior! Support for prototypes of main other than int main(void) and int main(int, char**) is implementation-defined! You can't go outside the Holy ISO Standard, or else demons will fly out of your nose! You can't do that... it's non-portable... it's not guaranteed to work... *curls up into a fetal position in the corner and sobs*

level 5
Original Poster5 points · 8 years ago

Um, I'm sorry.

level 6

Did you say mattress to Mr Lambert?

level 4
7 points · 8 years ago

That is not a valid transformation.

level 3
Comment deleted8 years ago
level 4

How exactly does one determine that going back to CL is the "easiest" thing to do?

There was no implication that it was the easiest thing to do (except possibly for smallfishbigpond him- or herself):

And there's the problem with languages like Haskell and F# (well, especially Haskell). You can't even understand the frikken "putStrLn" statement without talking about the MOST complicated feature of the language.

I consider it a design flaw, and went back to CL.

EDIT: Fixed the missing link.

level 4
1 point · 8 years ago

You actually don't have to deal with pathnames. An "x designator", in the terms of the hyperspec, is "any one of several different types that could be understood as an x". So you just use truename namestrings and it works, no need to use pathnames or logical pathname translations or anything. You don't even need to know what they are. I'm a common lisp coder, and I never use logical pathnames.

level 4

I abandoned it because on dominant implementation is not forthcoming and they cannot even get whether a drive letter is a device or a partition consistent on Windows.

level 5
[deleted]
1 point · 8 years ago

Why would there be a dominant implementation, any more than there's a dominant implementation of C++ or Fortran?

level 6

C++ doesn't need a dominant implementation because its standard isn't riddled with compromise, vagueness and strong recommendations. CL only needs a dominant implementation because key parts of the standard library have been made so generic that everybody implements them differently. As I said one major CL implementation sees a drive letter as a device and another sees it as a partition. Portable code is impossible. In C++ I do not have this problem between implementations.

Multiple implementations are practical if your standard is sane. While CL has a standard it is a crappy one. The various non-standardised Pythons are closer in behaviour than CL implementations (that all meet the standard) are.

level 7
[deleted]
1 point · 8 years ago

On the one hand, you're pretty much right about pathnames. They're too underspecified to be particularly useful. You're almost always better off just using namestrings and letting the implementation figure out whether "C:" is a drive or a partition.

On the other hand, the rest of the standard is much more precise. I can't think of one other language feature that's close to as problematic as the pathname stuff.

level 3
2 points · 8 years ago

I consider it a design flaw

It would be a design flaw if Haskell (like eg. Python) was designed with the explicit intention of being easy to approach even for beginners. But Haskell is clearly designed with the expectation that the user will make the upfront investment in learning how to use it.

I do agree that it is a major obstacle in learning Haskell that you have to understand the IO monad to be able to write "Hello world". However the Haskell motto is "Avoid success at all costs", so I'm not sure this is considered a design problem.

level 2
-9 points · 8 years ago(30 children)
level 3

I'm not really sure what your point is.

Currying is just a way for languages that lack multi-variable functions to simulate them via first-class functions.

This is obviously true. The whole point of currying is that functions that only take one input are no less expressive than those that take k. That's why Curry invented it.

But what if I want a function that returns a function that takes two variables?

This is trivial, you write a function that returns a function which returns a function.

This is exactly the same as a function that takes 3 arguments or a function that takes one argument and returns a new function that takes two arguments.

level 4
-6 points · 8 years ago(0 children)
level 5
9 points · 8 years ago · edited 8 years ago

You didn't understand what he meant. If you need to return a function that takes two variables, that works seamlessly with currying. Let's define a function with three arguments:

let foo a b c = a+b+c

Now we can use

let bar = foo 2 3

and bar is a function of 1 variable.

But we can also use:

let baz = foo 2

and baz is a function of 2 variables. As you can see currying works for any number of variables. The way it is described makes it sound like it only works for 1, though. The trick is that a function that takes two variables is the same as a function that first takes one argument and then another argument.

baz 1 2 = (baz 1) 2

So you could say that F# only supports 1 argument functions, but it looks like multiple arguments because of currying. Yes, it's true that currying is a way for F# to have multi argument functions, but they don't just do it for hipness' sake. Without curring you have to write fun b -> foo a b, with currying that becomes foo a. Not a big deal but nice to have, just like implicit this in C# is nice to have.

level 6
Original Poster0 points · 8 years ago · edited 8 years ago

let foo a b c = a+b+c

int Foo (int a, int b, int c) {return a+b+C;}

let bar = foo 2 3

bar = (x) => foo(x, 2, 3);

let baz = foo 2

baz = (x, y) => Foo(x, y, 2);

The trick is that a function that takes two variables is the same as a function that first takes one argument and then another argument.

boom = (x) => (y) => Foo(x, y);
partial = boom(1);
full = boom(1)(2);

Without curring you have to write fun b -> foo a b, with currying that becomes foo a.

So you save a couple of key strokes. Who cares? You are still expressing the exact same semantics and you haven't gained anything in terms of clarity.

EDIT: In fact you lost some clarity because now you can never tell by reading the code if your variable is a scalar or a function. You have to go all the way back to foo and count parameters.

level 7
3 points · 8 years ago

So you save a couple of key strokes. Who cares? You are still expressing the exact same semantics and you haven't gained anything in terms of clarity.

What? If you've got less keystrokes, (more accurately, less tokens), then that's a clearer way to express it. Some ways of expressing the same semantics can be clearer than others.

level 8
Original Poster0 points · 8 years ago · edited 8 years ago

No, fewer tokens don't automatically translate into clearer expressions.

Consider

a = f 1 2 g 3 4

Should that mean

a = f(1, 2, g, 3, 4)
b = f(1, 2, g(3), 4)
c = f(1, 2, g(3, 4))

And of course we still have my question about whether the final variable is a scalar or partially applied function.

There are also tradeoffs we haven't considered. If you have implied currying, then you lose the ability to have overloads based on parameter counts. (Unless you add tuples, at which point you lose your ability to curry.)

level 5

Why do you find it unacceptable? Why don't argument tuples satisfy you? I'd really love to understand the source of your misgivings.

level 6
Original Poster0 points · 8 years ago

Why don't argument tuples satisfy you?

Q: Why don't argument tuples satisfy you as an alternative to multiple parameters?

Given that I want to search for customers by first name, last name, and company, there are two ways to write the signature:

FindCustomer(string FirstName, string LastName, string Company)
FindCustomer( Tuple<string, string, string> params)

By using tuples I lose the ability to name my parameters. Now I have to refer to the documentation to discover what order the parameters go in.

Taking this a step further, perhaps each parameter is optional. To use this effectively you need named arguments, which are not possible when the parameters themselves don't have names.

level 7

Wait a minute. If we're talking about C#, it doesn't really have the option of currying (without hideous and pointless contortions), so we're in complete, absolute, unanimous agreement. Currying is pointless, I agree, in languages that don't have special syntax for currying. Have you tried each option in F#?

level 8
Original Poster1 point · 8 years ago

If we're talking about C#, it doesn't really have the option of currying (without hideous and pointless contortions),

Where g is defined as int g(int, int) you can curry it as such:

f = Curry(g);
partial = f(5);
full = f(5)(10);

The Curry function in C# is defined as

    static Func<int, Func<int, int>> Curry(Func<int, int, int> f)
    {
        return (x) => (y) => f(x, y);
    }

Now does that really look like "hideous and pointless contortions" to you?

level 9

does that really look like "hideous and pointless contortions" to you?

If you'll excuse my hyperbole, yes. Your Curry is not as general as it could be:

static Func<U, Func<V, W>> Curry(Func<U, V, W> f);
static Func<U, Func<V, Func<W, X>>> Curry3(Func<U, V, W, X> f);
static Func<U, Func<V, Func<W, Func<X, Y>>>> Curry4(Func<U, V, W, X, Y> f);

and so on.

level 10
Original Poster0 points · 8 years ago

Yea, that was just due to my lack of understanding of the C# syntax.

As there isn't any need for the helper function, in the future I will just write:

 f =  (u) => (v) => (w) .... g(u, v, w, ...)
level 8
Original Poster1 point · 8 years ago

We are talking about transitioning from C# to F#. This means you have to

  1. Prove currying is useful.

  2. Prove that F# is better at currying.

Number 2 is easy, but it won't matter if you don't get number 1 right.

level 9
2 points · 8 years ago

1.Prove currying is useful.

Look at examples of partial application.

level 10
Original Poster1 point · 8 years ago

FYI, when writing file parsers in VB I use partial application all the time.

level 7

Your first example is a non-problem in functional languages:

let findCustomer firstName lastName company = ...
let findCustomer (firstName,lastName,company) = ...

But I don't see why you'd want to write the latter either.

level 8
Original Poster2 points · 8 years ago

Don't forget the context. This is about demonstrating to OOP-style developers why they should be interested in functional languages.

level 8

for more information, look at pattern matching.

level 3

The concept of ‘currying’ just seems... well stupid

The theoretical point of currying is simply to show that multi-parameter functions are a special case of single-parameter functions, beyond the obvious vice-versa, so that the two are essentially the same (the word is "isomorphic"). No function expressed in either form has more expressive power than those expressed in the other. This means that it boils down to a matter of preference which style you find more comfortable writing code in.

Now, in most functional languages you have the concept of a tuple as a finite ordered sequence of values of possibly distinct types. Which means that you can have multi-parameter functions of sorts via tupled arguments. The big, big difference is that the tuple is actually a single argument and that you access its components by name by binding under a pattern match. As an example, suppose:

let hypot (x, y) = sqrt (x**2 +. y **2)

Here hypot takes as a parameter a single pair whose components are named x and y. You could even bind a name to the entire tuple so that you can use it without destructuring and restructuring it at each step:

let hypot ((x, y) as p) = refine_newton_raphson (x, y, coarse_hypot p)

(this is a nonsensical example). Think of invoking a super method or constructor with a complicated parameter list and how much keystrokes this would save, for instance.

level 4
Original Poster2 points · 8 years ago · edited 8 years ago

I understand what you are trying to show, but I don't think it will have the desired effect on most OOP developers.

For example, a C# developer will most likely see that as an argument to allow anonymous classes in function signatures.

level 3
2 points · 8 years ago

The replies have already gone through most of what I would say better than I could say it, but there's one important question for me. At first, you say:

The concept of ‘currying’ just seems... well stupid.

and it sounds to me like you are describing your point of view. At the ends of the other threads, you say:

Moreover, first class functions are easier for OOP programmers to understand without currying because the type signatures are simpler.

We are talking about transitioning from C# to F#.

This is about demonstrating to OOP-style developers why they should be interested in functional languages.

I don't think it will have the desired effect on most OOP developers.

All of these make it sound as if you are not advancing your own point of view, but rather arguing about the difficulty of convincing programmers used only to the object-oriented paradigm of the utility of the functional paradigm *.

Anyway, my question is: Should someone who wants to respond to your comment respond to you (who seems from your comment history to have a perfectly good grasp of functional programming, and the ‘meaning’ of currying), or to a hypothetical object-oriented programmer who is having trouble understanding why he or she should have to give up multi-argument functions?

* To this I would respond that currying is not, I think, a selling point of functional programming, but rather a feature that should be understood to make best use of them; certainly, were I trying to show someone my functional programming was fun, I wouldn't reach first for currying. Come to that, there's nothing about functional languages that forces them to curry (or about non-functional languages that forces you not to do so); for example, even the functional fragment of Lisp allows multi-argument functions.

level 4
2 points · 8 years ago · edited 8 years ago

(English usage tip: "used to" is a semantic unit that should not be broken up. "used to only".)

level 5
2 points · 8 years ago

(Really? “I'm only used to …” and “I'm used to only …” both sound terrible to me. I read ‘used to’ as roughly synonymous with ‘accustomed to’, and it's pretty clear to me that “I'm accustomed only to …” is the right way to say it.

They can't hear us when we're in parentheses, right?)

level 6
2 points · 8 years ago · edited 8 years ago

In my dialect of English, certainly.

I am used to "used to" having three meanings:

  1. accustomed to

  2. modifier indicating past-but-no-longer true

  3. for the purpose of

3 is just the individual parts being used together, and "only" can be freely stuck between them. 2 is more tightly bound, but it's technically using "to use" as an auxiliary verb, and so gets de-conjugated in certain cases: "Didn't you use to <verb>?" 1 really is the meanings of the unit, not the individual parts.

A Google search for "used only to" has only examples of 3. in the first few pages.

For "accustomed to", I am comfortable putting "only" in any place, before, after, or in between the two words, with slightly different connotations.

level 7

For "accustomed to", I am comfortable putting "only" in any place, before, after, or in between the two words, with slightly different connotations.

It's this that I'd miss if I were to give up the ‘used only to’ construction; I feel that it's definitely different in meaning from ‘only used to’, and subtly different from ‘used to only’ (though I couldn't really articulate why). Perhaps the problem for me is that my brain gets forced into sense (2) when it reads ‘used to only’.

level 4
Original Poster1 point · 8 years ago

Should someone who wants to respond to your comment respond to you (who seems from your comment history to have a perfectly good grasp of functional programming, and the ‘meaning’ of currying), or to a hypothetical object-oriented programmer who is having trouble understanding why he or she should have to give up multi-argument functions?

There isn't much difference. I am a developer who strongly believes in the advantages of OOP techniques. But I'm also sold on the advantages of first class functions. Likewise I strongly believe in Erlang's (gross misnamed) process style multi-threading.

To this I would respond that currying is not, I think, a selling point of functional programming, but rather a feature that should be understood to make best use of them;

That is where I am trying to go with this.

level 3
2 points · 8 years ago

Currying is just a way for languages that lack multi-variable functions to simulate them via first-class functions.

That's a side-effect of currying. The real point of currying is that it can often simplify partial application and even unify partial application and application. This can make for cleaner and simpler code. Combined with immutable values, this can make certain compiler optimizations work more uniformly.

level 4
Original Poster1 point · 8 years ago · edited 8 years ago

Partial application in Haskell involves passing less than the full number of arguments to a function that takes multiple arguments.

http://www.haskell.org/haskellwiki/Partial_application

Boring. Want that in C#?

g = Curry<int, int, int>(f, 2);

The definition of ApplyPartial is equally simple:

    Function Curry(Of TArg1, TArg2, TResult)(ByVal f As Func(Of TArg1, TArg2, TResult), ByVal arg2 As Targ2) As Func(Of TArg1, TResult)
            Return Function(x) f(x, arg2)
    End Function
level 5

Yes, now do it for three arguments, and four, and so forth. And have the compiler inline expressions.

level 6
Original Poster1 point · 8 years ago

I'll one up you. I'll do a partial application that takes a function of 5 arguments and applies them in pairs working from the inside-out. And this time I won't use a helper function.

        weird = (c) => (b, d) => (a, e) => Strange(a, b, c, d, e);
        result = weird(1)(2, 3)(4, 5);

And now in VB

    weird = Function(c) Function(b, d) Function(a, e) Strange(a, b, c, d, e)
    result = weird(1)(2, 3)(4, 5)
level 1

Wow.

From what the OP said NOT to do, it sounds like F# might actually be interesting and not just for math nerds which the presentation he sat through reinforced.

Does anyone have any links or material on F# that do the things he suggests? (e.g. doesn't use boring examples, shows how it's actual useful)

level 2

Watch this video - it's super entertaining and shows how you can use F# in a 'normal' development task

http://channel9.msdn.com/pdc2008/TL11/

level 2
[deleted]
-1 points · 8 years ago

F# is meant to be used for mathematical style programs. If you want to write database front ends then that's what C# is for.

level 3

You must be a woman. Because you're totally wrong.

level 2
-4 points · 8 years ago

Here and here.

level 3

And here.

level 1
3 points · 8 years ago

When explaining functional programming, I like to explain using the approach in "Why Functional Programming Matters".

Basically, it compares the replacement of "goto" with structured code (loops, conditions, later exceptions), with the replacement of mutable variable writes/reads and argument/return value passing.

goto's basically let you manipulate the control flow freely, but this means that understanding what happens in your program is difficult and correctness is difficult.

mutable variables, similarly, let you manipulate data flow (between mutable cells) freely, but this means that understanding what happens is difficult and correctness is difficult. Whenever you have one entity writing into a mutable cell, and another entity reading from it -- you could instead restructure the code to have the entities pass an argument or return value to one another.

This kind of restructuring, similarly to the restructuring that needs to be done to replace goto's with structured code, is not systematic and trivial. It takes careful analysis about what the code is trying to achieve with those lower-level primitives, and then encoding those with the higher-level ones (structured loops or arguments/return values).

Just like structured code reveals the structure of your control flow, functional programming reveals the structure of your data flow. It becomes clear what is defined in terms of what and how.

Additionally, when your code uses argument/return value passing rather than mutable cells -- the type system can help catch much more bugs. If you forget to write to a mutable cell, the type system will not catch that. If you forget to pass an argument or return a result, however, it will.

level 1

DON'T stress the F# Interactive environment

Heh, no REPL means dealbreaker to me in almost all cases.

level 2

You aren't the target though.

level 3

Then who is?

level 4

The Java and C# only guys who form the 'mainstream'. Anybody who demands a REPL is already in the group who would be prepared to accept new ideas. Frankly a REPL suggests Lisp, Ruby, Python or Perl. Other than the last I'd say those types of programmers are more likely to be open to functional programming.

I've always said this about functional. You should make it look as close to programming in C# as possible. Not necessarily the language but the use of tools and the programming work flow. What people react against is change and the REPL is in fact a draw back when trying to attract people from edit, compile, run cycle development. The number of alien aspects need to be minimised. People will pick up REPLs later on.

level 5

Frankly a REPL suggests Lisp, Ruby, Python or Perl.

Aside from the general scripting-language feel, Perl doesn't belong on that list unless you count Devel::REPL.

level 5
1 point · 8 years ago
level 6

The existence of a C# REPL doesn't really suggest anything. How many C# programmers use it day to day? The issue is not what is possible. It is what is expected. Maybe convincing C# programmers to start with a REPL and then introducing F# is a better approach.

level 7
2 points · 8 years ago

How many C# programmers use it day to day?

Do you know? You seem to be saying that it isn't used day to day.

level 8

In my experience it isn't used. All the C# programmers I've seen use VS and a traditional edit, compile, run cycle.

level 9
1 point · 8 years ago

Things change - new crops of programmers gain their first programming experiences without edit/compile/run.

level 2

Because REPL is the secret to productivity?

level 3

I wouldn't go that far (poductivity is a the sum of many things), but it is incredibly handy to try things out and learn new stuff without needing to go through the edit-compile-link-cycle again. I would say it encourages experimentation and that is quite important to me.

level 4
0 points · 8 years ago

I've got a "sandbox" C# project that compiles in less than a second (as it's almost empty) so I don't find REPL usefull for this kind of tasks.

level 5

It is not the length of compiling, it is the instant (no manual compile step at all) feedback that encourages exploratory programming. I know that compilers can be very fast so that a compile-run-cycle is not long but I have found out that the REPL changed my way of working so much that everything else feels kludgy.

level 1
7 points · 8 years ago

DON'T answer the inevitable "why should I care?" question with the word "productivity".

I hate to be the one to point this out, but every language ever introduced has held this up as a reason to switch to it, and none of them have ever really felt like they were a productivity boost, at least not in the long run. And if you answer with, "Because I just think that way", that's a FAIL on your part, because I can't see how your thinking changes mine. (You may also like the Pittsburgh Steelers, while I know they can't hold a candle to the New Orleans Saints—now where are we?)

Really? There is no productivity gain in rapid development between following languages: C++, Java, Python ?

level 2
[deleted]
3 points · 8 years ago

Really? There is no productivity gain in rapid development between following languages: C++, Java, Python ?

Yes, that's exactly the problem: whenever the words "increased productivity" are said, half of the audience imagines something along the lines of Java to Python, that the language allows you to be very productive at writing 20 line throwaway scripts. Another half interprets your words to mean that the language boosts productivity of mediocre coders who don't know about smart pointers and are afraid of templates.

level 3
2 points · 8 years ago

On the same token, features like list comprehensions, lambdas, terse syntax, specialized frameworks (Ruby, Django) make for a incredibly fast turnaround.

level 2
Original Poster2 points · 8 years ago

I can certainly attest to the jump from C++ to Java. As for Python, the .NET langauges stole enough to make that meaningless for me.

level 3

.NET languages are in the middle between Java and Python for me. Python is a lot simpler and terser. In C# it feels like you have to jump through hoops to encode your problem whereas in Python it's more like expressing your problem as opposed to encoding it.

Have you tried (Iron)Python seriously? I'm sure you'd love it.

level 4
3 points · 8 years ago

Python is a lot simpler and terser.

This gap has nearly been closed for me by c# 3.5 with Linq, static extension methods, local type inference and anonymous types.

level 5

Yep, it's better than it used to be. Lexical scoping is a big thing I miss in C#. And I dislike the boilerplate you have to write. Part of it is the language, e.g. you have to write out types, create a class when all you need is a function, decorators, indentation based syntax:

if(x){ // C# programmers usually put every { and } on it's own line
   ...
}else{
   ...
}

vs

if x:
   ...
else:
   ...

The other part is verbosity in the libraries. Compare working with sets in C# vs working with sets in Python. I doubt the gap can ever be fully closed without big changes to C#.

level 6
[deleted]
1 point · 8 years ago

Lexical scoping is a big thing I miss in C#

You mean in Python?

btw, what I really miss in Python is let clause in generator expressions.

level 7
1 point · 8 years ago · edited 8 years ago

No, no, in C#. Python has better lexical scoping, unfortunately it's not perfect either, especially if you mutate variables. I miss the full power of Linq in Python too, but for the common case Python's list comprehensions are slightly more concise.

level 8
[deleted]
1 point · 8 years ago

What? Python has abysmal lexical scoping: only function and class definitions create scopes, so variables from different blocks are spilled all around, captured by lambdas/nested functions unpredictably etc. And yes, implicit declaration makes it painful to modify anything in the outer scope. On the other hand, what exactly don't you like in C# scoping?

for the common case Python's list comprehensions are more concise.

If by concise you mean that for and if are shorter than from and where, and select is unnecessary, then yes, but I don't think that's important. If you mean that return value goes in front, then I strongly disagree, I prefer my variables being declared strictly before use (lexically), so OCaml, Haskell and others can shove their stupid mathematical idiosyncrasies where sun doesn't shine. And there are no more differences between LINQ and Python generators.

level 9

On the other hand, what exactly don't you like in C# scoping?

Nested methods/functions look ugly. Global scoped things have to be in classes, e.g. global variables have to be in a class. There are multiple scopes: one for classes and one for values. In Python classes are values, so there's only one type of scope. This isn't a big difference but the way Python works just fits my mind better. I come up with a solution and in Python I can write it down but in C# I have to pay more attention to how I encode it and worry about how to get data in the right place of the program.

I prefer my variables being declared strictly before use (lexically)

I strongly agree. When writing a list comprehension in Python I always start writing the code backwards.

[for x in xs]
[f(x) for x in xs]

This would be my ideal:

[x in xs: f(x)]

or maybe

[for x in xs: f(x)]

If by concise you mean that for and if are shorter than from and where, and select is unnecessary, then yes, but I don't think that's important.

Agreed.

level 10
[deleted]
1 point · 8 years ago · edited 8 years ago

Nested methods/functions look ugly. Global scoped things have to be in classes, e.g. global variables have to be in a class.

Agreed.

There are multiple scopes: one for classes and one for values.

Explain this with examples, please.

In Python classes are values, so there's only one type of scope.

No! Absolutely not, and this bothers me immensely! When you have nested functions, you can read any variable from the outer scope without any problems, because with functions you have true lexical scope -- all variable names are known at compile time (i.e. when source is compiled into bytecode). With classes it's different: after the class definition was executed, everything that was defined in its scope is collected in the class' dictionary and is not accessible by other means. A case in point: since class scope isn't lexical scope you can't access class members from a @staticmethod with unqualified name and have to use a fully qualified name, like MyClass.something. This sucks!

In fact Python has a fairly generous lot of gnarly suckage like this, I'd even go as far as to say that its object model is the most contrived of any language I've used, even more complex and scary than C++'s, unless you wander into template territory there. Yes, most programmers most of the time don't have to deal with this complexity, but as soon as you want to implement something nontrivial (which usually is a bad idea, but still) the maw of chaos is agape and waiting.

EDIT: I've remembered the case when Python class scope demonstrated its retardiation for me: I tried to make a decorator which collects decorated methods in a special field. So that I would be able to write

parsers = {}

@classmethod # or staticmethod, doesn't matter
def parser(cls, s):
     def wrapper(f):
           # here I'm trying to put f into parsers

@parser('blah blah')
def parse_something(self):
     pass

and then have a nice collection of all parsers. BAM! I can't refer to parsers directly because it's not a lexical scope, AND I can't use the fully qualified name either, because when the decorator runs the class is not defined yet! Catch 22!

level 6

write out types

Do you mean in declarations? You can use var for local variables, which are the majority of type declarations.

create a class when all you need is a function

Why would you need to do this? C# already has closures, delegates and even built-in generic delegates so that you don't have to declare your own delegate types.

decorators

Attributes give you some of what decorators or nice for but, yes, a dynamic language wins here.

indentation based syntax:

Yeah, I hate curlies and semicolons too. :(

level 7
4 points · 8 years ago · edited 8 years ago

Do you mean in declarations?

Yes, in member variable declarations and method arguments and type parameters.

Why would you need to do this? C# already has closures, delegates and even built-in generic delegates so that you don't have to declare your own delegate types.

public static class FooUtils
{ 
    public static BarType Foo(BazType x)
    {
       ...
    }
}

def foo(x):
   ...

Oh and another problem is that types sometimes get in the way. Then you can either ditch type safety and go dynamic or work around it by cut-and-paste programming. The most common scenario is a generic class/interface Foo<T> that has methods bar and baz, but if T supports some interface I then Foo<T> should support a method foo and Foo<T> should support interface I.

level 8

Yes, in member variable declarations and method arguments

Those do suck, especially member variables. Method parameters both me less because I like the safety of static types but don't want the slow compile times of a Hindley-Milner language. I also, personally, like seeing type annotations for a method because it's useful documentation to me.

type parameters.

Type inference covers some of this space. The only time you need to specify a type parameter is when there's no other way the compiler could infer it.

public static class FooUtils

Ah, now I understand. I'd like non-class functions too. Extension methods go part of the way. In practice, it's not too much of a problem for me. Only a very small fraction of my code has functions where there isn't already a logical class to put them into.

The most common scenario is a generic class/interface Foo<T> that has methods bar and baz, but if T supports some interface I then Foo<T> should support a method foo and Foo<T> should support interface I.

That doesn't line up with how I reason about generic types. Can you give a more concrete example here? I don't think I've ever run into the situation you describe.

level 7
Original Poster1 point · 8 years ago

create a class when all you need is a function Why would you need to do this?

It is rather annoying to always have to prefix your library functions with namespaces in C#. For example:

C#: a = HttpUtility.HtmlEncode(b);
VB: a = HtmlEncode(b)
level 8

My solution these days for that is to make it an extension method.

public static class StringExtensions
{
    public static string HtmlEncode(this string source)
    {
        return HttpUtility.HtmlEncode(source);
    }
}

a = b.HtmlEncode();
level 6
Original Poster1 point · 8 years ago

Well then there is VB. If you don't use strict typing, the only time you have to declare types is when implementing an interface or event handler.

level 7

Sure that's a plus, but one can hardly claim that VB is as clean as Python.

level 8
Original Poster2 points · 8 years ago

Hard to say, they both have warts, some of which are serious. But at least both of them need a lot less boiler plate code than C#. It is hard to believe they still have the same broken if, for, and switch statements that C had decades ago.

level 9

What do you mean by broken if, for and switch statements? Do you mean in C#? Broken for and switch I understand in that case, but what's wrong with if?

level 10
Original Poster1 point · 8 years ago

Common bug #1: Accidentally assigning instead of comparing

if (x = 0 ) 
    { DoSomething(); } //this never happens

Common bug #2: Accidentaly semi-colon on the if-block

if (x == 0 );
    { DoSomething(); } //this always happens

Common bug #3: Accidentaly semi-colon on the else-block

if (x == 0 )
    { DoSomething(); }
else;
    { DoSomethingElse(); } //this always happens

Common bug #4: Dangling else block caused by commenting out a line

if (x == 0 );
    { DoSomething(); }
else 
    //{ DoSomethingElse(); }
    
AlwaysDoThis(); // this may or may not happen

Common bug #5: Forgotten braces

if (x == 0 ) 
     DoSomething();  
     DoSomethingElse();  //this always happens
level 6
Original Poster1 point · 8 years ago

Compare working with sets in C# vs working with sets in Python.

Example please.

level 7

In math:

win(b) = exists n in b such that not win(b \ {n-1,n,n+1})

In Python:

def win(b): return any(not win(b-set([n-1,n,n+1])) for n in b)

Translate that into C#. It will look similar but not as nice.

Python: s1 - s2
C#: var temp = s1.Copy(); temp.ExceptWith(s2); temp

In Python sets are something you'd use all the time without making a big deal about it. In C# sets are syntactically heavy.

level 8
Original Poster2 points · 8 years ago

It is a pity that we can't use extension methods to add the missing operator overloads on C# classes.

level 4
Original Poster2 points · 8 years ago

Have you tried (Iron)Python seriously?

Yes and no. I am currently using IronPython as a scripting language in XAML. I see it as an alternative to writing value converters in VB or C#, but not as a primary language.

EDIT: Just to be clear, I strongly dislike dynamically typed langauges. However, since XAML data binding is already dynamically typed so given that context why not use the best available?

level 3
[deleted]
3 points · 8 years ago · edited 8 years ago

Dear .NET Programmer,

Yo dawg, I heard you like machines. So I built you a machine to run on your machine so you could have a program to run your programs.

Sincerely yours, C++ Programmer.

level 4
Original Poster2 points · 8 years ago

Dear C++ programmer.

I'm sorry but things aren't working out. Sure we had some laughs and we like the garbage collector you gave us. But the compilers, man those are really holding us back. We need to grow and that means rewriting them all in our own languages.

Sincerly yours, .NET Programmer.

P.S. We are taking Windows Phone in the divorce. You did enough damage to its older siblings.

level 2
0 points · 8 years ago

Depends. Sometimes the solution to a problem is most clearly expressed by some pointer arithmetic and bit-banging...good times.

level 3

Agreed, right tool for the right job withstanding in general though there is a big difference.

level 1

lol, next to his website I looked at the ".NET Developer Association meeting" blog. and it seems every meeting incorporates free pizza at 6:45 pm :D Stereotype bling bling

level 1

I hate to tell you this, but most of the developer community is not convinced that functional programming is "obviously" the right way to program. Attempting to take them deep into functional mojo is only going to lose them and overwhelm them and quite likely convince them that functional programming is for math majors. Use of the terms "catamorphism" or "monad" or "partial application" or "currying" in your introductory talk is an exercise in stroking your own ego, not in teaching the audience something useful.

Reddit, are you listening?

level 1

Anyone got links explaining in a manner described by this post? In written form as well, videos won't do for me.

level 1
[deleted]
1 point · 8 years ago

The Brisbane Functional Programming Group recently had a speaker on F#.

level 1

Ted Neward... the guy who called 'O/R mapping' the vietnam of software development, in public. And we should take advice from him about speaking?

level 1
[deleted]
0 points · 8 years ago

DO stress that F# can do everything C# or Visual Basic can do.

Although you can hook into all the .NET libraries and system calls the language is not suited for that.

The intended use of F# is for writing of libraries for financial or scientific computing.

Those libraries can be used in C# or VB or IronRuby or IronPython or whateverhaveyou for other bits and pieces that those languages are suited for.

level 1
[deleted]
-4 points · 8 years ago

DON'T use a demo based on a mathematical principle (like Fibonacci, factorial, or some other exponent-hugging formula.

Vegetable. I got offended by that. Fibonacci series and factorial isn't even proper math, it's something every self-respecting programmer should have deeply ingrained from calculus 101. Am I now supposed to put on a handkerchief when reading proggit?

level 2

Vegetable. I got offended by that. Fibonacci series and factorial isn't even proper math, it's something every self-respecting programmer should have deeply ingrained from calculus 101. Am I now supposed to put on a handkerchief when reading proggit?

Animal. I got engorged by that. Fibonacci series and factorial aren't even proper link-bait, they're things that every self-respecting internet junkie should have deeply ingrained from Usenet. Am I now supposed to put on assless chaps when reading proggit?

WTF are you trying to say?

level 3
[deleted]
1 point · 8 years ago

That proggit, like digg is going down the shitter. If the first point you're going to make is that fibonacci is 'too much math' then I'm sorry, but you suffer from mental retardation - it's no point discussing it any further. The sad thing about this is proggit has become a happy place for web 2.0 code monkeys - or else I wouldn't see stories like this.

level 2
[deleted]
0 points · 8 years ago

Vaguely a Monty Python reference? Remember he's writing for people presenting F# to C# devs - most of whom are writing large complex apps day in day out - not dinky little factorial implementations. If you want people to engage, you've got to show them what's in it for them - business apps guys don't need a neat factorial solution,.

Community Details

1.4m

Subscribers

3.7k

Online

Computer Programming

Create Post
r/programming Rules
1.
Keep submissions on topic and of high quality
2.
No surveys
3.
No résumés/job listings
4.
/r/programming is not a support forum
5.
Spam
Info

Related reddits

Specific languages

Cookies help us deliver our Services. By using our Services or clicking I agree, you agree to our use of cookies. Learn More.