DEV Community

Discussion on: Bringing it all together: Copy With Style

Collapse
 
lionelrowe profile image
lionel-rowe • Edited

It seems like your main argument is "I know Python and I don't know JS, therefore Python is more intuitive than JS".

The syntax and usage of JavaScript objects is almost identical to those of dictionaries in Python. Python's **kwargs is an additional type of syntax — useful, sure, but if anything less intuitive when you first encounter it. Compare:

Python:

def fn(**options):
    return options.foo

options = { "foo": 5 }

fn(**options)
Enter fullscreen mode Exit fullscreen mode

JS:

function fn(options) {
    return options["foo"]
}

let options = { "foo": 5 }

fn(options)
Enter fullscreen mode Exit fullscreen mode

Does the usage of ** really make the python version more intuitive, imagining for a moment that you don't have prior knowledge of any programming languages?

Thread Thread
 
thumbone profile image
Bernd Wechner

It seems like your main argument is "I know Python and I don't know JS, therefore Python is more intuitive than JS".

Can't agree there. The three observations shared stand. There is simply nothing inviting intuitive about x = myfunc({a: 1}). The ({ ... }) syntax beggars classification as "intuitive" regardless of you programming background (and while I draw a Python comparison because Python and JavaScript sit as two of the most popular languages just for the record I have a fairly heave background with a fair range of languages, off the cuff Basic, C, FORTRAN, Pascal, Ada, Perl, VBA, C# and yes Python, and I'm not feeling particularly Python biased at all).

But yes the syntax can be very very similar to Python (already observed and one reason for the comparison) and yet you never encounter x = myfunc({a: 1}) because like other languages (albeit far from all) it supports named arguments from the outset.

And from this 2. follows, using arbitrary anonymous objects as an argument to simulate that is far from intuitive. Familiarity with named arguments goes back at least to Visual Basic and isn't a Python bias. Arguably a VB bias ;-). But I don't think it a bias in any direction to observe that use of an arbitrary anonymous object as a vehicle to carry arguments flexibly is counter-intuitive, very probably no designed by intent but a community standard that emerged applying object to get a useful outcome.

I should add it's not 'bad'. It's fine, and works, and is a neat trick if anything. It's just not intuitive is all.

I should close though admitting that well intuition is by definition at some level biased, so it's not bias I would deny, so much as a specific one. To turn it around while intuition is a function of bias, it's a broad experience based bias and so unintuitive is almost anything that is novel, specific to particular language and not familiar or reminiscent of experience, or neatly mnemonic - easy to connect with familiar things. Novelty is mostly but not always unintuitive I guess. But I'd reserve that word when the novelty is not a really new idea, so much a peculiar quirk.

Thread Thread
 
thumbone profile image
Bernd Wechner

Does the usage of ** really make the python version more intuitive

I missed that, sorry. But the answer there is no, it doe snot. But one encounters such syntax very rarely in Python indeed. The unpackers * and ** are not intuitive at all now, and require careful explanation to all newcomers. But you can read a LOT of Python code and never encounter them and that includes a LOT of Pyton code with functions that take large numbers of named arguments.

Your more like to see:

def fn(opt1=def1, opt2=def2, opt3=def3)
Enter fullscreen mode Exit fullscreen mode

Though you will at times come across fairly early in Python exposure:

def fn(*args, **kwargs)
Enter fullscreen mode Exit fullscreen mode

and there's nothing intuitive about that no, it needs careful explanation and instruction ;-). One gets familiar with it, it's not hard to learn, but sure as heck ain't easy to divine what it means on first encounter no.

Thread Thread
 
lionelrowe profile image
lionel-rowe • Edited

Ahh I see, yeah I'm showing my lack of familiarity with Python here — I only knew about **kwargs, not arg=val.

I'd still argue that named arguments that can be supplied in any order are an additional concept to learn on top of positional arguments, whereas passing an object literal to a function is understandable as long as you understand positional arguments + objects (or call them "dictionaries", "hash maps", etc if that helps nomenclature-wise. JS objects are not Java objects.)

It's true that accepting default values can be a little confusing in JS:

function fn({ foo = 1, bar = 2 } = {}) { /* ... */ }

// or...
const defaults = { foo: 1, bar: 2 }

function fn(opts) {
  const { foo, bar } = { ...defaults, ...opts }
  /* ... */
}
Enter fullscreen mode Exit fullscreen mode

However, the unintuitiveness here is only from the implementer's point of view. The consumer still has a simple and intuitive API they can use:

fn() // supply no arguments, fallback to defaults
fn({ bar: 7 }) // supply an `options` object with partial or full options
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
thumbone profile image
Bernd Wechner

the unintuitiveness here is only from the implementer's point of view

Spot on! In fact two important distinctions here:

  1. Intuitiveness exists in the user and developer realm completely independently. They are two very different things. And historically developers inability to role play the intuitiveness of a user (use case definitions and such) led to developer-centric UIs.

  2. All intuitiveness is a personal experience and hinges on ones experience base and what, thanks to that, feels familiar and "intuitive" (meaning little more than guessable form the base of familiarity I suspect). It is only then and when someone again is able to role-play the "average" newcomer say to a language that it has any meaning to claim intuitive or not.

On 2. it is simply the case that yes I made the claim (and still would) that for a newcomer to JavaScript with almost nay other or now coding experience the x = y({ ... }) syntax engenders a "huh?" feeling which is my general gauge for "not intuitive". Intuitive features I imagine engendering more of a "oh, yeah" feeling when encountered. They just sit well. But one thing that runs counter to intuition is a pattern such as the exemplified one in which I see one set of braces immediately inside another of a different type. So I was left, reading and learning to try and work what on earth, that actually means. Of course as confessed in the article learning it came with a "Doh!" feeling as I was of course familiar with the basic object instantiation syntax options already, it was ot a discovery, the discovery was that I hadn't noticed this very subtle implicit anonymous (unnamed) object instantiation in a list of arguments.