
Verb-Noun vs. Noun-Verb - Sindisil
https://simblob.blogspot.com/2019/10/verb-noun-vs-noun-verb.html
======
thomascgalvin
> 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.

~~~
karmakaze
Actually 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
One 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) ) )

~~~
greggman2
I know most will disagree but I find code the above hard to read. I'd much
prefer

    
    
        const people = list.stream();
        const peopleOlderThan50 = people.filter(??);
        const average = peopleOlderThan50.mapToInt().sum() / peopleOlderThan50.length;
    

Or some such thing. The more complex the chain the harder it is for me to
read. Does anyone else have that experience?

~~~
joostdevries
I agree. Naming parts of your code is important. An alternative to named local
vals is to either use named functions instead of lambdas:
people.filter(olderThan50) or (I use Kotlin) use named extension functions:
people.countOlderThan50()

~~~
splittingTimes
In any nontrivial application, doing this for many of your types, does this
not bloat your API considerably, which adds to the cognitive load?

------
c3534l
I remember doing some research on language for a psychology course in college
and I think it's important to warn hacker news that the expieriences people
have with nouns being more intuitive and fundamental is absolutely not a
cultural universal. Westerners place unusual emphasis on nouns and while it
may be that "get" is less specific than "item_id" in English, it may be more
be the opposite if you speak a language that has specific and concrete verbs
and abstract nouns. This is one of those times where your intuition about what
is logical and obvious might be wrong.

~~~
TeMPOraL
Kadir beneath Mo Moteh.

Speaking of which, I wonder whether we'll program in Tamarian one day. Whether
we'll be able to build functioning software from a really high-level
abstractions, and perhaps not try to micromanage it too much.

(And then when something goes wrong, the program will simply say, "Shaka, when
the walls fell.")

~~~
Izkata
You maybe be interested in the Petrovich language:
[http://www.dangermouse.net/esoteric/petrovich.html](http://www.dangermouse.net/esoteric/petrovich.html)

------
kbenson
> vim's commands like d0 are verb then text selection (noun), whereas in more
> conventional text editors (including Emacs) you'd first select some text
> (the noun) and then invoke a verb like delete.

I would say vim is also noun-verb as you can select text and then tell it to
perform an action on it, but supports convenience methods for verb-noun, or
just verb. It's just that most the verbs also have a default selection they
apply to as well, whether it be a character, a line, or some larger block of
content. Thus, 'x' deletes one character, but 10x deletes 10 characters, using
'v' to select text and then x deletes the selected characters. 'dd' deletes
the default (current) line, '10dd' (or 'd10d' to mix it up) deletes the next
10 lines, using 'v' to select a range of lines and then 'd' deletes those
lines. Additionally, you can just define a range of lines to apply a command
do in command mode: 10,20d deletes lines 10-20.

~~~
kerkeslager
I think vim makes more sense if you think of it like a Forth. In a general
sense, the entire language is noun*verb (zero or more nouns followed by a
verb).

I know what you're going to say, "dw is a verb noun!" but really, it's not. w
is verb--it's a function that, in this case, takes the d function and applies
it to a word. The fact that it is a verb is proven by the fact that the
expression executes when you type the verb. It's unfortunate that the vim verb
"w" corresponds to the English noun "word", but that's probably the best that
could be done given there are only so many keys on the keyboard.

------
ljp_206
This gives words to a frustration that I've had with many roguelikes. I don't
want to /drink/ -> /ladder/, I want to do ladder things with the ladder, which
should be a very short list. Freedom does not great game design make (by
default).

~~~
kbenson
The problem with applying this to some roguelikes, such as Nethack, is that
part of the fun is finding out what you can do. Getting a handy contextual
menu when you find a sink, or an alter, or whatever makes the game easier and
less confusing, but also takes away a wonderful aspect of it when you learn or
hear about some new crazy aspect of it.

That's not to say it doesn't have a place in roguelikes, just that each game
needs to carefully consider what it brings to the table, and also what it cuts
out.

~~~
otikik
> takes away a wonderful aspect of it when you learn or hear about some new
> crazy aspect of it.

It might be useful to think about this in term of how many players it affects.

My opinion is that for each seasoned roguelike player who enjoys this
"wonderful" aspect, there will be multiple roguelike newbies who will be
discouraged by the unfriendly UX and just leave.

~~~
alchemism
That encapsulates what happened in the transition from text parser (keyboard-
driven) games to mouse-driven games: discoverability went up, complexity went
down; the first generation of gamers lost interest and a second larger
generation of gamers came into being.

~~~
cortesoft
Not everyone lost interest... I loved keyboard driven games, and I love mouse
driven games, too.

------
excessive
One of the things I dislike about the OO noun.verb() syntax is that frequently
you have multiple nouns. For example in some graphics systems, you've got a
canvas to draw on, a pen which knows styles for line thickness or dashes, a
brush for how to fill, and a shape to be drawn. Who owns the verb? They kind
of all do:

    
    
        canvas.draw(pen, brush, circle)
        circle.draw(canvas, pen, brush)
        ... and so on
    

The other issue I have is in closed object systems where you can't add new
methods to classes in the library. Say I want to add a new type of shape,
maybe an emoji face composed of several circles. Depending which class owns
the methods, my new smiley method stands out from the other shapes which are
provided by the library, and I think the lack of symmetry is ugly:

    
    
        canvas.draw(pen, circle)
        draw(canvas, pen, smiley)
    

For simple cases, inheritance solves this, but then you get into worse trouble
when Alice builds a derived class to support smileys, and Bob builds a
separate derived class to add stick figures. Which version of the canvas do I
instantiate to support both? Maybe this implies the method should be on the
shapes, but I can contrive other examples which break that too. (Another
approach is monkey patching, which has it's own flaws, and so on.)

There aren't many languages which support multimethods, but overloading
functions is sufficient for statically typed cases, and it's appealing (for
me) to have the same syntax for "builtin" methods and ones you add yourself:

    
    
        draw(canvas, pen, brush, circle)
        draw(canvas, pen, brush, smiley)
    

Other people have mentioned languages with "uniform function call" syntax
(where f(a) and a.f() are synonyms). I guess that's ok if you're in the
"there's more than one way to do it" camp. I don't think that completely
addresses the problem though. I could make more examples, but this post is
getting long already.

For what it's worth, I really dislike it when languages implement operator
overloading for binary operators as methods on the first object without a way
to dispatch to the second object. This makes it very difficult to have your
new types play well with the builtin or library provided types. Binary
operators really are functions with two arguments.

~~~
gambler
This whole comment section tells me that almost no one on HN really
understands OOP.

OOP is not about nouns. It's about establishing protocols between subsystems.
What you're describing are the typical fake "dilemmas" of someone coming from
a static, class-oriented programming languages like Java.

Look up Class Responsibility Collaborator exercise.

~~~
betenoire
> It's about establishing protocols between subsystems.

Is that what it's about? I try to establish protocols between subsystems
without OOP quite often. Are you referring to message passing specifically?

~~~
excessive
> Is that what it's about?

I'm pretty sure most people who strongly like OOP are sure their particular
definition is the correct one. I haven't seen many people agree about what
that definition is though. I generally dislike OOP, but perhaps that's because
my definition is "encourages implementation inheritance". As you're keen to
note, the standard list of other things (encapsulation, message passing,
dynamic dispatch, interface inheritance, and even "establishing protocols")
are available in a lot of other languages which people don't generally
consider OO.

Perhaps I'm ignorant, but I like my way of doing things, and a.f() is less
attractive to me than f(a) for all the reasons I listed.

------
breck
This seems to jive with my experience, but I'm trying to formulate a back-of-
the-envelope mathematical explanation. Here's my thinking: nouns are in 3D
space and verbs are in the 4th dimension (you need the concept of time to have
a verb).

By going "noun-verb", you are fixing the first 3 dimensions and leaving one
remaining (hence the ~1000x reduction in search space for autocomplete). By
going "verb-noun" you are only fixing 1-dimension, leaving the other 3
unknown, and autocomplete would have a larger search space.

Putting it another way. If I started a story "the year was 2015", I've only
narrow the one time axis, but the "noun/place" hasn't been narrowed at all, so
you still have a sphere of possibilities. However, if I started a story "we
were on the Golden Gate bridge", I've pinpointed the 3-dimensions of
place/noun, and now the reader only has to pinpoint where on the "time-line"
we are. And even that timeline has been shortened to a segment of ~100 years.

~~~
jodrellblank
_However, if I started a story "we were on the Golden Gate bridge", I've
pinpointed the 3-dimensions of place/noun, and now the reader only has to
pinpoint where on the "time-line" we are._

How does the reader trying to guess the date narrow the choice of verbs?

You might be on TGGBridge jogging, and the date is irrelevant. It seems like
fixing the location to TGGBridge narrows the possible verbs, but it’s still a
huge list - “we were on” means you could be doing anything people can do -
photographing, touring, jogging, sketching, working as a bridge repair crew or
structural engineer or a vehicle breakdown van or an Uber driver or protesting
or meeting up in a well known location.

In English, “I was driving..” implies a vehicle, but “a car..” doesn’t imply
you were driving it, or necessarily doing anything to/with it at all.

~~~
breck
> How does the reader trying to guess the date narrow the choice of verbs?

My thinking is when someone visualizes something they need to visualize the
place/noun first and the verb (what happened over time). The first requires 3
dimensions and the latter just one more.

------
nlawalker
This is exactly the thing that has always bothered me about PowerShell. A lot
of PowerShell's effectiveness derives from the number of nouns that Microsoft
has built support for, and a defining trait of any given script is usually the
set of nouns it operates over, so it's weird to me that all the commands start
with the verb.

~~~
GordonS
I've never been able to quite put my finger on why I loath Powershell so much,
but yes, I think this is part of it. I also dislike how verbose commands are
(and the shortened versions are not safe to use cross-platform), and the weird
Pascal-Kebab-Casing-Hybrid of idiomatic Powershell also irks me.

Still, there is something else... I just don't like it.

~~~
pfranz
I could never get used to PowerShell, but in languages like Bash I /really/
like using short flags in the REPL (for speed), but long flags in scripts (for
legibility). Unfortunately, this means there's a higher bar to learn and I've
never seen a way to enforce this (I rarely see others use this convention). I
hoped PowerShell would address this or the ISE (maybe great autocomplete
negates the need for short flags?)

~~~
guhidalg
Disclosure, I work at MSFT and I have a special place in my heart for
PowerShell.

PowerShell provides incredibly flexible syntax, enough that it can satisfy
most styles of script writing.

The practice you describe (short names in CLI and long names in scripts) can
be achieved. A couple of things to note about how PS binds arguments to
function calls: 1\. If you omit names, the parameters are bound positionally.
1\. If you use names, you do not have to type the full name. It is sufficient
to type an unambiguous prefix of the parameter name and the most appropriate
parameter will be selected.

So for example in the CLI you can just to `ls -r -fi _.csproj` whereas in a
script you can use the fully self-documenting `ls -Recurse -Filter_.csproj`.

Hope this helps!

~~~
partdavid
Another commenter complained about short aliases not being safe cross-
platform, and this is an example. In powershell core on Unix systems 'ls' is
the 'ls' command, not an alias for Get-ChildItem. So I would say the correct
"long" version for your example is 'Get-ChildItem -Recurse -Filter .csproj'.

In my opinion this is a non-issue (at least when comparing powershell to other
shells) because the number of cases where you have to worry about bash command
'X' actually being different from your system (even across varieties of Unix-y
OSes) is much greater than this handful of convenience aliases in powershell.

------
csande17
I like Nim's approach to this issue: `f(x)` and `x.f()` are completely
equivalent to one another.

[https://nim-lang.org/docs/tut2.html#object-oriented-programm...](https://nim-
lang.org/docs/tut2.html#object-oriented-programming-method-call-syntax)

~~~
juped
This feature is also in D. I am a fan.

~~~
Inityx
Rust checking in, UFCS present

------
posterboy
I clicked the link hoping it was about language. But it is about rogue likes
and programming.

Since english can verb nouns like nominalization, i can't tell what the
benefit is. one boards the board of a ship, levers a lever, and locks a lock.

We "lockpick" more often than we "save face" perhaps English is a head-first
language.

In formal writing, a difference exists between nominal and verbal-style.

~~~
bcyn
The article is more about user experience than English language nuances.

Take one of your examples, you're much more likely to know you can "board"
once you know there's a "ship." Without the ship as context first, only people
who are already familiar with ships know that boarding is even an option.

This provides a poor experience in terms of discoverability.

------
Symmetry
Relatedly, there's a vim-like editor that is all about moving from verb-noun
to noun-verb.

[https://github.com/mawww/kakoune](https://github.com/mawww/kakoune)

~~~
codesections
This was mentioned in the posted link

------
mrkeen
I used to prefer car.drive(), now I prefer drive(car).

I don't buy the auto-completion argument. Can my IDE really tell me all the
ways I can use an Integer? I don't think so.

When it hit home for me was when Java 8 lacked Stream.takeWhile(predicate) and
I decided to implement it for myself. I could implement takeWhile(predicate,
stream), I could not implement stream.takeWhile(predicate).

~~~
UserIsUnused
Also, the autocomplete argument isn't a big argument, as writing is the less
time consuming task in the process.

~~~
stkdump
Autocomplete is one thing. Getting a list of suggestions is more important,
because you might not know the name of the function.

~~~
UserIsUnused
I agree, I guess that noum.verb() is indeed better to find those

------
lotyrin
I wonder if the ergonomics of text based adventure in SOV-order languages
is/was substantially improved for this reason.

北に行く (north, go) ポーションを飲む (potion, drink) スライムを戦う (slime, fight).

------
jkcxn
There's no reason you couldn't type `noun.` and get autocomplete to
`verb(noun)`

~~~
nlawalker
Or just support calling "verb(noun)" as "noun.verb()" all the way through:
[https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax](https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax)

~~~
unholiness
At Onshape we're considering doing this for our language FeatureScript[0], as
discussed here[1]

This would make the call e.g. v1->cross(v2) syntactic sugar for the call
cross(v1, v2).

The main reason it's not just an obvious win for autocomplete and readability
is that it provides for multiple ways to do one thing, and is one more thing
you need to know when learning this new language. Rather than having some code
call plane->yAxis() and other code call yAxis(plane), it _might_ be nicer to
have only one way.

The other counterargument: the OOP-like syntax could support the expectation
that polymorphism works like e.g. Java, where e.g. v1.cross(v2) would only
considers the type of v1 when deciding which overload to call. FeatureScript
has multiple dispatch and will consider the types of all arguments when
choosing an overload.

All that said, the change it seems like a win overall, but we're waiting for
the language to mature more to see if clearer arguments emerge.

[0] [https://cad.onshape.com/FsDoc/](https://cad.onshape.com/FsDoc/)

[1]
[https://forum.onshape.com/discussion/comment/33495/#Comment_...](https://forum.onshape.com/discussion/comment/33495/#Comment_33495)

~~~
nlawalker
_> Rather than having some code call plane->yAxis() and other code call
yAxis(plane), it might be nicer to have only one way._

One option is a linter/formatter that can warn and configurably push you in
one way or the other.

------
leibnitz27
Hang on. Is no-one else here just blown away by the fact that the guy lucked
into meeting Garriot & Watson? Man, I'd have given my right arm for that as a
kid.

~~~
jedberg
Yeah that part stuck out to me too. Lucky guy!

------
teddyh
See also Steve Yegge’s _Execution in the Kingdom of Nouns_ (2006):

[https://steve-yegge.blogspot.com/2006/03/execution-in-
kingdo...](https://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-
nouns.html)

~~~
ergothus
The part of the article talking about dropping to one verb ("use") made me
think of the same thing ("execute").

The benefit to verb/noun (or noun.verb) is getting BOTH. If you effectively
drop the verb, you lose out on half the communication.

To use another comment, you may not want to quaff a ladder, but it is a bad
idea to assume you just "ladder", and if assume too narrow a field it leads to
frustrations. (In programming or in games. Back when I looked into text
adventure games (interactive fiction) there was a truism that "use" was a
_bad_ verb)

If you ARE wide enough....then you have little difference between noun verb
and verb noun except for the effort required.

Honestly, I was more interested in the first part of the article, that talked
about checking the state if the world rather than a sequence if steps.

------
ken
The flip side of this, that they don't mention, is that this asymmetry exists
only if you design your interfaces in FP / OO languages differently. Most OO
designs I've seen have a large number of classes, each with very specific
methods. Most FP designs I've seen have few (or even zero) custom types, and a
large number of methods can apply to a large number of types.

As Alan Perlis said back in 1982:

> "It is better to have 100 functions operate on one data structure than 10
> functions on 10 data structures."

When I'm writing in a FP language, it's true I don't get much autocomplete
help, but the upside is that I've got 100 core functions that operate on
almost anything. Even if you flipped around the order of the syntax on screen,
autocomplete wouldn't help much, because you can apply any verb to any noun. I
rarely have to convert between types, and when I do it's a couple words at
most.

When I'm writing in an OO language, with typical class libraries and
frameworks, I get a lot of help from autocomplete, because once you know the
"type", there's only a few things you can do with it. The corollary is that I
usually spend half my program converting from the type I have to the type that
I need.

(Think about English. We could simplify the language by eliminating words like
"eat", and just say "I'm going to go _use_ lunch", but then we wouldn't have
the word "eat" available for any other nouns, even where it'd be helpful and
clear.)

> It is better for programmers if they can choose from two medium length lists
> than to have to choose from a very long list (where a lot has to be typed
> before it's useful) and then a very short list (where not much is gained).

This doesn't tell the whole story. As they say, you write code once, but read
it many times. I'm perfectly OK with giving up autocomplete (for writing) if
it means I don't have to spend twice as many lines of code (for writing _and_
reading) to convert an X to a Y just so I can call f() on it.

The more generic the functions, the less code I have to write, and having less
code has huge benefits across the board -- for writing, reading, debugging,
testing, performance, and so on. Autocomplete can be nice, but it's not nice
enough to want to sacrifice everything else.

------
mbo
Note that not everyone FP lang is verb-noun. Sure, most are, but your
F#/Elixir/Scala's are more often than not written in a noun-verb form with the
`|>` operator or something vaguely equivalent (syntax extensions in Scala's
case).

------
BariumBlue
I think what the topic gets towards is that if you view all possible actions
as a multi dimensional array of (all nouns)*(all verbs), it makes sense to
first choose the one of (nouns, verbs) that is initially the smaller set

------
taormina
I find this whole conversation interesting as someone who is working on a text
adventure (shameless plug: [https://danger.world](https://danger.world)).

I personally chose verb-noun, but it would be very simple to flip it around.

------
gnuvince
Is this really verb-noun/noun-verb or verb-object/object-verb?

~~~
shadowgovt
verb-object / object-verb is more specific in the context of this story, yes.
And indeed, when you introduce indirect objects or other fanciness, additional
dimensions of complexity can be introduced (GUIs, for instance, can have
ambiguity in terms of whether object-verb-indirect_object is represente by
click-command-click or modclick-modclick-command).

