5 ms·
> Something I noticed at the time was that the syntax for functional languages tends to be verb then noun: f(x), whereas the syntax for object oriented language
by thomascgalvin 7y ago
> Something I noticed at the time was that the syntax for functional languages tends to be verb then noun: f(x), whereas the syntax for object oriented languages tends to be noun then verb: x.f().... There's a big difference in usability though: auto-complete.
Auto-complete also really helps with discoverability. Consider checking for the presence of a key in a map/dictionary. In Java, auto-complete will quickly lead you to `map.containskey(key)`. In Python, though, you'd have to know that the syntax is `if value in dict`.
Now, let's check for the presence of a value. Auto-complete again quickly leads you to `map.containsValue(value)`. In Python, Google tells me that it's `if value in dict.values()`, which seems more difficult to stumble upon.
And that's for a built-in data structure. A lot of my job involves trudging through other people's code, trying to figure out how they architect their ball of cats. Auto-complete is a great tool for that; it lets you quickly and easily poke around, and see what the various nouns in the system can do.
- saagarjha 7y agoI also think that the object-oriented syntax matches my thinking process more closely: for example, I have an array of strings, and I want to convert them to numbers, pick only the odd ones then sum them rather than "I want to sum some things…things which I'm filtering by parity…which are actually strings I'm converting to integers".
- scarejunba 7y agoThat's how the thread-last/first macros help in Clojure. You sort of specify a pipeline: ``` (-> list parseInt isOdd sum) ``` Is the same as ``` (sum(isOdd(parseInt(list))) ``` Particularly useful if you're pulling a deeply nested key out.
- karmakaze 7y agoActually FP is more often verb-verb as in compose these verby thing together in this way to make a new verb then finally give it a starting noun.
- thomascgalvin 7y agoOne of the things I like about Java's streams is that it makes the verb-chaining more obvious, at least to me. list.stream().filter().mapToInt().sum() just reads better to me than sum( mapToInt( filter(list) ) )
- rtkwe 7y agoYeah I much prefer that style because it reads left to right like I naturally read as an English speaker. It flows more naturally from the original object and the changes applied to it.
- Twisol 7y agoAgreed. Some functional languages (like F#) have a pipelining operator |> that gives the same syntactic impression: list |> map (1+) |> filter odd |> sum
- codr7 7y agoAnd other languages, such as Forth; don't need one. list map filter odd sum
- Twisol 7y agoHuh. I would've expected it to be `odd filter`, not `filter odd`.
- the_gipsy 7y agoI have found myself using pipes many times in Elm, because they make the code so much more readable. Now I understand why! I haven't seen an autocomplete that works on pipes. But with a good type system, it is technically possible to list all compatible functions that take "noun" as first parameter. Sometimes you supply partially applied functions (also with pipes in noun->verb order) and that's not so easy to match: noun |> verb1 |> (otherNoun >> verb2) |> etc But perhaps even functions that take "noun" as nth parameter could be suggested.
- dyarosla 7y ago+1 for “ball of cats”. That’s a new one for me.
- Twisol 7y agoI think that can be solved without bringing objects into the mix -- functions are usually grouped up into modules of some kind, so leading with `Foo.` (or `foo::` in C++, etc.) still provides a useful level of scoping that can aid autocomplete. On the other hand, tools like Hoogle [0] let you search for functions based on type, so you can search for e.g. `ByteString -> _` to find functions that take a bytestring. There's no reason the same paradigm can't be applied in an IDE.
- stouset 7y agoThe Python approach also exposes unnecessary details and by doing so causes a performance hit by forcing you to get a list of keys/values and then find out of what you’re looking for is in them. This is slower than what the dictionary could do internally: hash the key and check if there’s an entry for it in the backing store.
- klodolph 7y agoThe .values() method does not return a list, it returns a view object. If you write ‘value in m.values()’, it invokes the __contains__() method. (Note that this cant be a hash check because it’s not testing the presence of a key.) (Also note that the story is different if you look at sufficiently archaic versions of Python.)
- stouset 7y agoFair enough!
- cortesoft 7y agoThis is one of the reasons I like ruby better than python... none of the magic 'dunder' methods... if you want to define a custom adder for your class, so "foo + bar" works, you do "def +()" in ruby instead of "def __add__ ()" in Python.... I love that ruby just uses the actual operator instead of some arbitrary method name you have to remember.
- lifthrasiir 7y ago> none of the magic 'dunder' methods Ruby do have equivalents to Python magic methods... disguised as normal methods. For example Python `__hash__` is Ruby `hash` and both are used by built-in dict/hash values and you should be aware of that fact in both. There are some philosophical differences as well, Python likes to have standalone functions that are customized via magic methods (e.g. `str` vs. `__str__`, you don't normally call the latter) and in Ruby everything is method (e.g. `to_s`). It really seems like a matter of taste.
- delusional 7y agoIt's real great to know that I can get and set all the fields. Thanks previous programmer.
- AmpsterMan 7y agoThis is one of those paradigms that I don't understand in Java. It's the most trivial of trivial encapsulations.
- Izkata 7y agoIt is (was?) the primary way to maintain binary compatibility between versions of class files, where switching an attribute to a method (if logic such as verification needed to be added in a future version) would break that compatibility.
- mthoms 7y agoSetters I get (see what I did there?). It's the superfluous getters that simply return the values I'll never understand.
- Izkata 7y agoSee my cousin comment - it maintains compatibility when changes are internal to the class. For example, if a field was switched from concrete to derived, you'd have to switch the attribute to a getter, which would break compatibility with the previous version.
- kerkeslager 7y ago> Auto-complete also really helps with discoverability. Consider checking for the presence of a key in a map/dictionary. In Java, auto-complete will quickly lead you to `map.containskey(key)`. In Python, though, you'd have to know that the syntax is `if value in dict`. This isn't an argument for noun-verb over verb-noun, though it's an argument for more homogeneous syntax. `if value in dict` isn't noun-verb OR verb-noun. There's not really a reason that f(<tab> couldn't complete with arguments (and it does in many systems). I think if you wanted to use autocomplete to make a point, you'd have to argue that it's more effective somehow to complete on verbs than on nouns.
- bobbyi_settv 7y agoBut exactly because it's easier to "stumble upon" the right answer, I think this may be worse for games. I like feeling as if it's necessary to come up with the solution in my head and then do it. It's not satisfying if every puzzle can be quickly solved by selecting each item in the room and trying the couple actions the game offers you for that item.