Live data from Hacker News

Leaving Python for JavaScript

hire.jonasgalvez.com.br

61–70 of 112 posts

Re: Leaving Python for JavaScript

#61
> the spread operator

How?

JS:

  var args = [0, 1, 2];
  myFunction(...args);
Python:

  args = [0, 1, 2]
  myFunctions(*args)
A more complicated one:

JS:

  var args = [0, 1];
  myFunction(-1, ...args, 2, ...[3]);
Python:

  args = [0, 1]
  myFunction(-1, *args, 2, *[3])
As used in list building; JS:

  var parts = ['shoulders', 'knees']; 
  var lyrics = ['head', ...parts, 'and', 'toes']; 
Python:

  parts = ['shoulders', 'knees']
  lyrics = ['head', *parts, 'and', 'toes']
"A better way to concatenate arrays"; JS:

  var arr1 = [0, 1, 2];
  var arr2 = [3, 4, 5];
  arr1 = [...arr1, ...arr2];
Python:

  arr1 = [0, 1, 2]
  arr2 = [3, 4, 5]
  arr1 = arr1 + arr2
(Though the star notation works here too.)

I omit JS's use of ... on objects; Python's class system works differently — and IMO, more rigorously — than JS's, making ... less sensible on Python objects. (Python focuses much less on passing around untyped key-value bags and more on strongly typed classes IMO; both are possible in both languages, but the idioms around them differ, and I think Python's idioms tend more towards having a well defined class with well defined attributes, and not having just a bag of attributes, moreso than JS at least, and I feel that direction (well defined classes) leads to more robust code. In particular, it forces you into naming your concepts, and defining their set of attributes: a simplistic type definition.)

> all functional Array methods

Python has map, reduce, etc., as well as generator and list comprehensions which are often easier to use.

> async functions

Python and JavaScript have practically identical syntax in this area.

> there's no acceptable way to pass a function body to another in Python

I find it very acceptable that if your function body is more complicated than an expression, that you're forced to pull it out and name it, frankly. I think it does good things for fighting complexity, and this just isn't something I worry about day to day while using Python. But I will concede that Python does lack a syntax for passing a function in an expression context.

(But I would also note JS's screwed up named-function syntax; in Python:

  def foo():
    # body
is a valid statement. JS's:

  function foo() {
    // body
  }
is not a valid statement, and can only appear in certain, particular contexts. In particular, the following is not valid JavaScript, though many implementations will do The Right Thing™, I'm told:

  if(true) {
    function foo() {
      // body.
    }
  }
[2])

> My code usually revolves around higher order functions, reduce(), map(), etc. I can't remember the last time I wrote a regular for loop in JavaScript.

Because JS for a long time (until ES6's for(… of …) syntax) lacked a for loop (the C style look, and for(… in …), do not count, as they do semantically different things), which is why you're using forEach().

> arrow functions

The best thing about arrow functions is the sane binding of `this`, a problem notably absent in Python to begin with.

> [Python's] class definition boilerplate is still hard to look at

This is sometimes true; I find the attrs[1] package helps greatly here for small, struct-like classes.

[1]: https://pypi.python.org/pypi/attrs

[2]: http://kangax.github.io/nfe/#expr-vs-decl

Re: Leaving Python for JavaScript

#62
post #32

Earlier quoted context omitted.

No one likes callback hell but I believe they meant that you can just pass a function expression directly. No need to define a named function. It's the difference between: let doubled = nums.map(x => x * 2) and this: def double(x): return x * 2 doubled = map(double, nums) (my Python is pretty rusty so maybe there's a better way of doing that)

You can do the exact same thing in Python, and this is not any new feature: doubled = map(lambda x: x * 2, nums) JS it's just not as explicit with what you're exactly doing.

If you want more than a one-line lambda, however, you're in for a rough time, and need to go the route of

    def foo():
        # ... four lines here ...
    modified = map(foo, items)

Re: Leaving Python for JavaScript

#63
post #18

> there's no acceptable way to pass a function body to another in Python. There are sentences which are telling a huge incompetence about the person using these. This sounds the same story to me as "We used tech X, but X is shit/can't do something so we switched to Y, and Y is awesome and fast." Where the person switching was just incompetent with X but it would have been perfectly solvable and they just do a totally…

This guy does sound incompetent. Sounds like he likes js because it's easier to use callback hell with multiline anonymous functions.

You can pass a function as a callback or something else in python. You just give the function a name then pass it. No function literals.

Also he's talking about async/await in koa... does this fool realize that async/await is built into python?

I'm proficient in both python and js and I have to tell you, python is light years ahead of js in terms of language design.

Re: Leaving Python for JavaScript

#64
post #32

Earlier quoted context omitted.

No one likes callback hell but I believe they meant that you can just pass a function expression directly. No need to define a named function. It's the difference between: let doubled = nums.map(x => x * 2) and this: def double(x): return x * 2 doubled = map(double, nums) (my Python is pretty rusty so maybe there's a better way of doing that)

You can do the exact same thing in Python, and this is not any new feature: doubled = map(lambda x: x * 2, nums) JS it's just not as explicit with what you're exactly doing.

The pythonic way is to use a list comprehension for maps and filters.

Re: Leaving Python for JavaScript

#65
> So with JavaScript you've got arrow functions, the method shorthand definition syntax, the spread operator, destructuring assignments, all functional Array methods and async functions.

This confuses me quite a bit, there are nuanced differences between these ideas in the two languages but at the surface these are things that very much exist in both languages

arrow functions:

  (x,y) => { x + y } 
vs.

  lambda x,y: x + y

method shorthand definition:

  MyObj = {
      foo(x,y) { return x + y }
      bar(x,y) { return x * y }
  }
vs.

  class MyObj:
      foo(self, x, y): return x + y
      bar(self, x, y): return x * y
spread operator:

  function add(x,y) {
      return x + y
  }
  add(...[1,2])
vs.

  def add(x, y):
      x + y
  add(*[1,2])
destructuring:

    [a, b, ...rest] = [10, 20, 30, 40, 50];
vs.

    a, b, *rest = [10, 20, 30, 40, 50]
functional array methods:

    forEach(["Wampeter", "Foma", "Granfalloon"], print);
vs.

    list(map(print, ["Wampeter", "Foma", "Granfalloon"]))
async methods:

    function resolveAfter2Seconds(x) {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(x);
        }, 2000);
      });
    }

    async function add1(x) {
      var a = resolveAfter2Seconds(20);
      var b = resolveAfter2Seconds(30);
      return x + await a + await b;
    }

    add1(10).then(v => {
      console.log(v);  // prints 60 after 2 seconds.
    });
vs.

    async def resolve_after_2_seconds(x):
        await asyncio.sleep(2)
        return x

    async def add1(x):
        a = resolve_after_2_seconds(20)
        b = resolve_after_2_seconds(30)
        return x + await a + await b

    loop = asyncio.get_event_loop()
    loop.run_until_complete(add1(10))
There's a lot of fun differences between the origins of these features and how they work but the sentence to me doesn't quite to the idea of "Leaving Python for JavaScript" justice

Re: Leaving Python for JavaScript

#66
post #32

Earlier quoted context omitted.

No one likes callback hell but I believe they meant that you can just pass a function expression directly. No need to define a named function. It's the difference between: let doubled = nums.map(x => x * 2) and this: def double(x): return x * 2 doubled = map(double, nums) (my Python is pretty rusty so maybe there's a better way of doing that)

You can do the exact same thing in Python, and this is not any new feature: doubled = map(lambda x: x * 2, nums) JS it's just not as explicit with what you're exactly doing.

Now try a multi-line one in Python.

Re: Leaving Python for JavaScript

#67
post #62
post #32

Earlier quoted context omitted.

You can do the exact same thing in Python, and this is not any new feature: doubled = map(lambda x: x * 2, nums) JS it's just not as explicit with what you're exactly doing.

If you want more than a one-line lambda, however, you're in for a rough time, and need to go the route of def foo(): # ... four lines here ... modified = map(foo, items)

What's rough about giving a function a name?

Re: Leaving Python for JavaScript

#68
post #18

> there's no acceptable way to pass a function body to another in Python. There are sentences which are telling a huge incompetence about the person using these. This sounds the same story to me as "We used tech X, but X is shit/can't do something so we switched to Y, and Y is awesome and fast." Where the person switching was just incompetent with X but it would have been perfectly solvable and they just do a totally…

I really like chaining Promises in JavaScript. The Python way to do this doesn't seem as powerful (what if you want to inject a parallel set of async operations at some point in the chain?): https://stackoverflow.com/questions/43325501/how-do-i-write-... - JS also supports async/await but the advantage of JS is that you can return promises (or parallel combinations of multiple promises) from inside promises so any li…

You realize your promise code is ugly af. All your code is nested within other functions and chained with dots. It's not clear.

For imperative code the goal is to write code that is just as clear as writing a single threaded algorithm: a simple list of steps. Promises and callbacks DO NOT ACHIEVE THIS GOAL.

That stackoverflow post showed a python solution that's infinitely cleaner than js. Python skipped callbacks and promise chains and jumped directly to the best way to do async operations... async/await.

You want to shove a parallel set in an async chain of operations? Here's the way to do serial and parallel async operations in Python:

    async def main():
        # run them sequentially (but the loop can do other stuff in the meanwhile)
        body1 = await get_body('http://httpbin.org/ip')
        print body1
        body2 = await get_body('http://httpbin.org/user-agent')
        print body2


        # run them in parallel
        task1 = get_body('http://httpbin.org/ip')
        task2 = get_body('http://httpbin.org/user-agent')
    
        for body in await asyncio.gather(task1, task2):
            print(body)
You see that code? Way more clearer way more understandable than your promise chain. Python has it's problems but your promise code is not powerful at all, it leads to over complicated code and just slightly better than callbacks.

Re: Leaving Python for JavaScript

#70
post #21

Earlier quoted context omitted.

I have been in your position about a year ago. The approached that helped me, was to not worry about all this. Just start somewhere; and in a month or two, you would mostly know which libraries you need to add to your project. The best way to go about it, is to check a few popular open source projects; what libraries they typically use. > I am also asking if any of those libraries will be around in a year? You can ch…

I mean no offense, but the "just use it you'll get used to it" strategy seems the antithesis of the goal of engineering as a discipline. A materials engineer simply cannot afford to pick concrete unless she knows the specific load and weathering characteristics of it. The same should be true for software projects. You shouldn't use cheerio because everyone uses it in their project, but because you've looked through t…

It's important to not disregard the expertise of a fellow developer before you have decisive proof that their approach is genuinely poorly thought out. That is to say: Give people the benefit of the doubt.

As an outsider the big amount of dependencies look daunting, but the tendency in JavaScript as of late has been to use small libraries that do one thing, do it well, and play well together with others (Composable is the buzzword). Whereas Java and C# for instance tend to have macro libs that "Have it all bundled in".

It's different approaches, and you might not _need_ absolutely everything, then again you might, and you are in a much worse position to evaluate that as an outsider than the developer who made it.

All in all, I quite like the JavaScript approach where pieces are just that, instead of a pre-built lego set which I'll have to study to build, I have small pieces which give me more flexibility to take my project where I want to take it. The tradeoff, and they naturally exist, is that dependency maintenance is substantially more difficult, and the likelihood of something you use being straight up abandoned raises for each dependency you add. Which might lead to having you either maintain that piece yourself, or abandon it, and add another piece that fulfills a similar role.

Post reply on HN