4 ms·
I second the notion that fluency is a language syntax problem that should not be solved with the design of interfaces. Smalltalk also solved this problem with
by braythwayt 9y ago
I second the notion that fluency is a language syntax problem that should not be solved with the design of interfaces.
Smalltalk also solved this problem with the semi-colon, but for some damn fool reason we followed C syntax but didn't find an alternative. And now we're trying desperately to replicate `&.` in every library and language, but we still don't have an easy way to write:
someObject
.doThis();
.doThat();
.dontForgetToFinishUp().
- bonesss 9y agosomeObject |> doThis |> doThat Thing |> doThat OtherThing |> dontForgetToPayTheBill or let getErDone = doThis >> doThat Thing >> doThat OtherThing >> dontForgetToPayTheBill someObject |> getErDone [not just pseudo-code, that can be compiled with the right definitions]
- hvidgaard 9y agoAnd that in essence is not really any different than an extension method in C#. At least not from maintainability point of view.
- bonesss 9y agoThe function chaining is a game-changer, if you're talking about maintainability... The temporary variables are eliminated,and the type-based chaining self-verifies for new modifications, neither of which you get in C#. Also, thanks to better support for higher-order programming, common post-launch activities like performance upgrades and async tweaking happens with stronger guarantees and oodles less code. In terms of essence: namespace shielding and modular composition gives numerous opportunities for logical encapsulation and complexity management that are not feasible thanks to C#s extension semantics and extension method requirements. All of the above can be defined in one type, for example, instead of multiple... The end product is just wildly more cohesive in F#/OCaml, with more options throughout to produce more maintainable solutions. F# can also use (a slightly improved), version of C#s extension semantics, as needed. But the functional composition, currying, Discriminated Unions, and exhaustive pattern matching in conjunction with the module syntax yield a final product that is markedly smaller and distinctly more maintainable than it's C# counterpart. Not to mention: from a syntax and readability perspective this just destroys its Fluent Interface counterpart, in about a third as many LoC. Start looking into things like custom operator support, DSL support, computation expression support, etc, and the maintenance improving possibilities just blow the .NET baseline out of the water.
- hvidgaard 9y agoI completely agree that F# is superior to C#, I use it when I can, but the gain from "fluent extensions methods" in C# is significant, and improves the code quite a bit. The main benefit over F#, is the pool of developers that understand C# is significantly bigger. This is a parameter I need to take in to consideration because of the developers I hire, there is few and far between the one that grok F# and FP in general.
- bonesss 9y agoFluent extension methods are better than no extensions at all, I agree :) I tend to look for general competence in new devs, because that persists across platforms and pivots. In general it's odd that we expect devs to know every language, tech, and cloud platform under the sun but draw the line at basic mathematical concepts mapped into programming decades ago... Using both sum and product types is fundamental to proper modelling, IMO. I also think comparison between C# and F# based on "tricky" FP concepts is really odd in modern times... On the one hand: if a new hire can't grok FP in F#, how can I trust them to do serious work in C#? OOP & FP synergize wonderfully, and the language has been openly trending towards FP ideals for a decade now. Those FP concepts are now modern idiomatic C# and also very important in tricky domains... On the other hand, if I'm doing work that makes me think correctness is even a little important why would I want to do it in a language almost-as-good that provides no guarantees and requires more complexity? Why bring a footgun to the party if I'm already worried about quality and some rando new hire? Seems like people who don't grok the basics would do better in a stricter environment with less room for f-ups. For my money I'll readily take a mild bump in on-boarding costs for productivity, production, and correctness guarantees forever. Not to mention the improved caliber of candidate one gets from finding self-selected A-grade techies and advertising an aggressive dev environment.
- hvidgaard 9y agoIn the current situation, getting a competent dev that seems to be able to grasp FP naturally, does not require a mild bump in on-boarding cost, but a significantly higher salary. Right now I'm hiring developers right out of school and put them through a mentor program, hoping that they turn out good.
- mhomde 9y agoI always wanted a language that was built upon the concept on just passing things forward in a pipe, and was like an hybrid between functional and c style languages, like: someobject => doThis() => doThat() => dontForgotToFinishUp() then you could also possible send multiple objects into that pipe: obj1, obj2 => doThis() => doThat() => dontForgotToFinishUp() you'd have to have some semantics for sending them separately, as an ienumerable or as parameters but perhaps that could be done (obj1, obj2) => doThis() => doThat() => dontForgotToFinishUp() [obj1, obj2] => doThis() => doThat() => dontForgotToFinishUp() add on top of that something that could abstract away multithreading/tasking in certain cases (automatically assigning them to tasks) and I'd be a happpy coder :)
- roywiggins 9y agoForth, maybe?
- kortex 9y agoI spent a half day playing around with something very similar to this. I wanted a concise language for describing data pipelines in Pandas, and was (ab)using python dunder methods (operator overloading) to this end. Like: `data | groupby, "author" | mean` Would create a graph object, which could be lazily evaluated, run in Dask, TF, etc. It started to get ugly when passing in multiple parameters into a function. I had to watch out for left and right associativity, and manage casting of arguments. It was a fun little experiment but I'm not sure how much it would actually improve workflows. If that sounds interesting, let me know and I'll poke at it again.
- wenc 9y agoI'm not sure if you are aware, but there are several efforts out there to give Python a more data-pipeline-friendly (composable pipe) syntax: 1) Coconut: http://coconut-lang.org/ http://coconut-lang.org/ 2) https://github.com/JulienPalard/Pipe https://github.com/JulienPalard/Pipe 3) Pandas also has a new dataframe pipe method. https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.pipe.html https://pandas.pydata.org/pandas-docs/stable/generated/panda... I would look at those before rolling out a custom solution.
- erpellan 9y agoKotlin solves the problem elegantly with the 'apply' and 'run' extension functions. fun foo() = Runtime.getRuntime().apply { addShutdownHook(Thread { println("Bye!") }) traceMethodCalls(true) exit(404) }
- hungerstrike 9y agoKotlins `apply` seems exactly like the much maligned `with` statement from JavaScript, which has been deprecated. Why is it elegant here, but deprecated there?
- m00g00 9y agoTook the words right out of my mouth (literally, and 5 minutes faster). Why? I'd say because Douglas Crockford.
- abiox 9y agoi suspect some or many of the reasons it's discouraged in js do not apply to kotlin. as we all know, js has... unique constraints in it's design. why is it deprecated in js?
- m00g00 9y agoWhich is awfully similar to JavaScript's much maligned 'with' statement. Never understood the FUD and 'considered harmful' screeds against it. Yes I'm aware of the performance/optimization concerns, but honestly, the whole javascript language is a massive performance/optimization concern and we've managed pretty well. Simple things like changing style properties on DOM elements: with(element.style) { display = "block"; marginLeft = "5px"; background = "green"; } And of course with 'with', everything is a fluid interface, and with the flexibility of being able to enter code between the function calls.
- oweiler 9y agoWith `Arrow`, a Kotlin FP library you can do that "foo" pipe capitalize pipe toUpperCase pipe reverse