hello,
the curried form of defining parameters fits the functional style more and the tuple form matches the way arguments are passed in .NET methods.
In "Expert F# 2.0" the authors recommend currying:
- for prototyping and scripting ;
- when you intend to produce a residual function from the original one through partial application of arguments.
If you're designing a vanilla .NET component for use from C# or VB then stick with the tuple form to achieve a clearer result from the perspective of these languages.
F# allows you to combine the curried and tuple forms to produce a function that takes some arguments in tuples and others in iterated form.
Regards, Taha.
>tuple form matches the way arguments are passed in .NET methods.
There may be some confusion between "tupled form" and "comma form" - the latter <i>could <i>be passed as a tuple or not depending on if you're calling a let-bound function or a method. (Though you do say "tuple form" and not "tuple" passing.) Eg: fn 1 2 --> two params to let-bound fn fn 1,2 --> one param (2-tuple) to let-bound fn o.meth(1, 1) --> two params to method o.meth((1,1)) --> one param (2-tuple Tuple<int,int>) to method The first and third forms do not create tuples, and will be faster than the second and fourth, all other things being equal. It would be less confusing (and allow some forms w/o parens where parens are needed now) if the typle-creating operator was not "," but let's say, "@" - but the comma matches long-standing CS and maths definitions. We are allowed certain shortcuts/hybrids that complicates things: o.meth 1 --> shortcut (no parens) one param to method 1 |> "123".Substring (1,2) |> "123".Substring() I'd have to look at the IL to see if the pseudo-currying in the last two cases here is actually optimized away, which it could given that the functional objects aren't passed out of the scope of the immediate computation. Given that tuples aren't free (they take time to construct and destruct and memory allocated, even if the .Net MM is very good w/such short-lived objects), the rule for me whether to use tuples or not is whether the args make sense as an individual "packet" of data unto itself - e.g., only use them if you already have a tuple retreived from a data-structure, or if a new tuple's lifetime is longer than entry-point of the called fn - if the tuple args are immediately unpacked, you can use two parameters to avoid overhead of the tuple. (I beleive tuples to (at least named) fn's are always tuples, and are not yet optimized away, even when immediately unpacked by tuple-args in the fn decl. and never referenced again.) In my code, I rarely use tuples as args -- except for a few cases where it's very common -- (1) in-line piplined expressions where .Zip is used to bundle-up args and pass to fun's that transform the args along the way, and (2), canonial "flyweight" data-structures such as (x,y) pairs for points, where it's easily understood what's going on, even late at night :) If you've ever programmed in Prolog, you know how it's easy to roped-in by tuples with auto-unpacking (or in the Prolog case, terms of arbitrary arity and functor name, not just ",") - but how it can also quicly become a mess. Hope that helps?
Well I hope it helps. I'll probably have to read it 3 or 4 times to get it all clear in my head.
This is one of the things that I just don't like about f#. I don't think I've ever felt confused before about simply passing parameters to a function.
Thanks for the reply, it does help.
Derek
> I don't think I've ever felt confused before about simply passing parameters to a function
Maybe you should implement a full Algol68 compiler just for fun, then come back here :)
When you think about what your getting -- almost all of OCaml, a full .Net language peer, and extras like builder expressions, etc., the small initial pain is worth it.
Plus, if you want to write "pure" F# code, then there's no confusion at all - args are always seperated by spaces, and where there's a comma, there's always a tuple. It's only OO code interoperating with .Net methods where (as in most languages) you seperate params with a comma that there is any possible confusion - and if there is, then chances are something won't parse quite right, and you'll know right away by the underline in the IDE.
> Maybe you should implement a full Algol68 compiler just for fun, then come back here :)
No need... just download Algol68 from [here].
Algol68 only has two ways to pass arguments. By Value, and by Reference.
Eg in C one would write:
int procx(int v, int *r){ printf("%8d %8d\n", v, *r); }
In Algol 68 one would write:
proc procx = (int v, ref int r)int: ( printf($8d" "8dl$, v, r) )
At sourceforge find Binaries for Linux (.rpm&.deb), MacOS-X and Windows7.
And the source will compile on Solaris and all BSD Unixes.
So just add the following line to as the first line of your code and write scripts in Algol68!
#!/usr/bin/a68g
[The latest Algol68G "interpreter" (2.0.1) also interoperates a "compiler" for _units_. Hence in these portions of code run as fast as C code]
The core of the Royal Signals and Radar Establishment's Algol68RS compiler (written in Algol68RS) is also available for download from [sourceforge algol68toc download].
Enjoy
NevilleDNZ
BTW: For this October there is a €68 bounty for the "best"(*) complete port of the most current Algol68g implementation to the Android.
(*) Marcel van der Veer can be the ultimate judge.
[Going OT...]
Yeah, I ran across that implementation after I posted. (I admit I'm rusty here - but the types of things you could pass by ref or val was great for it's day - and I was also thinking more of Alogol60 thunks (pre-closures) and the things you could do with them.)
When you look at Algol68 it's really amazing what was there -- we really lost quite a bit going to C - other than implementability :) (You could see why if Multics was as complex as Algol how it could of fell over in its day.) We're only getting some of these features back now in mainstream languages recently, though they've always been around in one lang. or another. (The worst move to me was the dichotomy between statements and expressions.)
Consider this - one can emulate most required thunking in gcc in a couple of ways,
e.g.
$ cat sum.c
#define SUM(i, max, f) ({ double sum = 0; for(i=0; i<max; i++) sum+= f; sum;})
double sum(int *i, int max, double (*f)()) {
double sum = 0; for(*i=0; *i<max; (*i)++) sum += f(); return sum;
}
main(){
int i;
printf("SUM sq=%f, sum sq=%f\n",
SUM(i, 25, i*i),
sum(&i, 25, ({ double sq(){ return i*i; }; sq; }))
);
}
$ gcc sum.c -o sum; ./sum
SUM sq=4900.000000, sum sq=4900.000000
Needless to say, both that above can have side effects. But so too did Algol60 thunking. Algol 68 allows the second method, which has the advantage of being strong typed.
Here is the original hack coded in 40 different languages:
* [link:rosettacode.org]
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
I've been wrestling with learning F# for some time now. I started on a project but found myself constantly bumping up against roadblocks in my understanding the functional way of doing things as opposed to my normal imperative/oop way.
So I picked up a copy of the Little MLer and began working through everything translating the ML into F# and trying to come up with my own solutions for each exercise before looking at how they implemented it in ML. I did something similar 20 years ago with the Little Lisper, and it has proven to be mostly as enjoyable as I remember when I was coming to grips with Lisp and Scheme when I was in school.
One thing I constantly find myself unsure of is whether I should be defining functions to use individual parameters vs tuples. I see a lot of code that seems to just use a tuple as an argument (maybe because it looks familiar to the way we'd invoke a function in an imperative language?). But sometimes I see people switching back and forth between a tupled param set and individual ones. Is there some guidelines or reasons why I should choose one over the other?
For instance here's the function combine_s that I still haven't gotten my head around:
type 'a list =
Empty
| Cons of 'a * 'a list
let _base l2 =
l2
let rec combine_s l =
match l with
| Empty -> _base
| Cons(a,l) -> make_cons a (combine_s l)
and
make_cons a f =
let mc l2 =
Cons(a, f l2)
mc
I saw the way someone else implemented make_cons was with the params as a tuple, either way can be made to work, is one way more appropriate?
If you're interested you can see how things are progressing at a public Subversion repository I've setup here:
[link:www.assembla.com]
I'm currently working on Chap8.fs
Derek