News for hackers. Stuff that matters.
Re:Test for lists in Cython by Gravityloss on Monday April 19, 2021 @08:36AM (#26862027)
I was a huge fan of Matlab way back. I wrote a hundred small Matlab programs for usage in the research department of the company I worked in. Doing data operations in Matlab was way more elegant than in say, Numpy which I tried later. Development was fast and ergonomics were good.

After using Ruby for years, returning to Matlab style code in Julia felt somewhat awkward. Instead of my_array.length you have length(my_array). In my personal preference the method call is just a nicer way of doing the same thing. The single-instruction-multiple-data or dot notation sometimes worked and sometimes didn't, so you had to resort to loops anyway.

    % Julia
    a=[1 2 3 4]
    a.^2
    log.(a)

    # Ruby
    a=[1,2,3,4]
    a.map{|element| element.pow(2)}
    a.map{|element| Math.log(element)}
Ruby and map or each have their verbosity but overall it feels a more robust "hammer" for general programming tasks. On the other hand, Julia can be really dense and still easy to understand.

Other languages of course take some of these things even further. Maybe some day I will find an ergonomics and nicety first successor to both.

Plotting with two Y axes or generating histograms in Julia was also way harder than I remember it being in Matlab. Also manually having to load the file before every run to see the changes in action added a lot of overhead to the workflow.

The workflow I was used to in Matlab involved very frequent making changes to code, running of the code that usually made some plot. Which is one command in Matlab, and plotting was fast, in 2001 already, on Windows NT 4. In Julia, you have to first load the modified file, then run it. Plotting takes a long time. One just can't get nearly as productive with it in 2021, compared to Matlab of 2001 vintage.

What language would I pick if I had to do some quick analysis from some tables downloaded from the internet? Probably Julia still. If I had free access to Matlab, I would probably use it though.

Re:Test for lists in Cython by vchuravy on Monday April 19, 2021 @08:45AM (#26862100)
Broadcasting and map are two different operations. If all the inouts have the same shape broadcast is equivalent to map, but in Julia you can also just use map.

`map(el->el^2, a)`

and inspired by Ruby

``` map(a) do element log(element) end ```

The latter being syntax sugar for the former.

Re:Test for lists in Cython by jhgb on Monday April 19, 2021 @08:40AM (#26862058)
> Instead of my_array.length you have length(my_array). In my personal preference the method call is just a nicer way of doing the same thing.

Well...they're both method calls, aren't they? (So they're both the nicer way?)

Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @08:56AM (#26862210)
Those who are attached to the class-based OOP model used, for example, in Python will find the dot notation more natural. But Julia’s multiple dispatch is a superset of this, and unarguably more powerful and flexible. Python OOP leads to monstrosities like

       >>> ', '.join(['1', '2', '3'])
     '1, 2, 3'

       >>> '1, 2, 3'.split(', ')
     ['1', '2', '3']
Re:Test for lists in Cython by deetsb on Monday April 19, 2021 @09:21AM (#26862430)
As I’m clearly missing the bigger picture, what do you find to be super offensive about this?

I read the first as the concat symbol applied to an iterable leads to string concated by the concat symbol.

I read the second as an iterable broken by split symbol leads to an iterable of the chunks.

Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @09:38AM (#26862601)
It’s hard to remember what order to put things in, because the two methods follow opposite conventions. And that’s because this type of OO design has no obvious method of organization.

In the first case, I want to do something to a list: join it into a string. So, clearly, I need a list method? But no, I need to engage in some form of indirection; for some reason, I need to reach for a string method. Even if there is no string that I want to use as a delimiter. In that case, I need to use a string method on an empty string.

OK, I’ll play along. Now I want to take the string and split it into an array. Now that I’ve been educated, I know better than to try the sensible thing. Pre-enlightenment, I would have reached for a method applied to the thing that I wanted to transform. But now I know I should think backwards, and use a method applied to the delimiter. OOPs.

Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @09:41AM (#26862639)
Here it is in Julia:

     julia> join([1 2 3], ", ")
     "1, 2, 3"


     julia> split("1, 2, 3", ", ")
     3-element Vector{SubString{String}}:
      "1"
      "2"
      "3"
Note how they are both functions. The data that they operate on is the first argument, in both cases. The optional second argument is the obvious next most important thing, the delimiter. Other optional arguments come after that. There is nothing to remember, because it makes sense.
Re:Test for lists in Cython by diarrhea on Monday April 19, 2021 @10:33AM (#26863169)
The Python FAQ itself adresses this: https://docs.python.org/3/faq/design.html#why-is-join-a-stri...

You'll have to decide if you find that convincing. I understand your point and kind of wish I hadn't read this thread because I'm more torn than before.

Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @10:53AM (#26863381)
Not convincing exactly, but I’m glad to know the thinking behind it, thank you. How are you torn?
Re:Test for lists in Cython by deetsb on Monday April 19, 2021 @11:25AM (#26863787)
That’s fair Lee. I think I’d accidentally stumbled upon the logic for .join acting on the separator rather than the iterable, but I do agree it’s awkward unless you’re trying to figure out why it is (which is poor design), and certainly not how most people think, especially with the inconsistency of split not acting on the separator.
Re:Test for lists in Cython by nostoc on Monday April 19, 2021 @09:24AM (#26862468)
That's not a failure of OOP, but a failure of design.

This could have easily been avoided if `join` would have been a method of the list object, not the string object. But we're stuck with this now.

Re:Test for lists in Cython by duckerude on Monday April 19, 2021 @11:24AM (#26863774)
If join were a method on lists then you wouldn't be able to use it with other iterables. Putting it on str is more useful, if more confusing.

Maybe it would be better as a standalone function. But then you'd either have to import it or it would pollute the global namespace.

Other OOP models offer different solutions.

Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @11:40AM (#26863992)
The Julia join function works on any iterable whose members are or can be converted into strings.
Re:Test for lists in Cython by adgjlsfhk1 on Monday April 19, 2021 @03:07PM (#26866734)
That requires multiple dispatch.
Re:Test for lists in Cython by jhgb on Monday April 19, 2021 @09:22AM (#26862442)
Multiple dispatch is usually class-based as well.
Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @09:27AM (#26862498)
Not in Julia.
Re:Test for lists in Cython by jhgb on Monday April 19, 2021 @11:38AM (#26863974)
It doesn't have named types on which methods get dispatched?
Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @11:41AM (#26864010)
Yes, but those are not classes, in the sense of Python or other OOP language classes.
Re:Test for lists in Cython by jhgb on Monday April 19, 2021 @11:54AM (#26864173)
Named types that can be dispatched on are classes, see CLOS. Hell, even in Python, classes are pretty much the named types that you can dispatch on, although of course, in Python, you generally can't create different kinds of types that can't be dispatched on like types satisfying a predicate - at least to my knowledge you can't, so the difference is somewhat less tangible there.
Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @12:10PM (#26864379)
In Julia they are not classes in the sense that the term is normally used in, for example, Python. Classes bind together data and methods, which is what leads to all the problems. In Julia functions are generic, and specialized to methods acting on arbitrary combinations of types; they are freed from the data.

https://arstechnica.com/science/2020/10/the-unreasonable-eff...

Re:Test for lists in Cython by jhgb on Monday April 19, 2021 @12:24PM (#26864553)
> Classes bind together data and methods

Not in CLOS, from which Julia's mechanisms are derived (which leads to the question why not CLOS but Python of all things should be used as a source of "normal sense" of anything Julia-related). In CLOS, classes bind together data, generic functions name abstract operations, and methods represent specific code that deals with implementing a generic function for a particular combination of type arguments.

> which is what leads to all the problems

I don't think anyone is disputing that here. There's a reason why CLOS didn't do any of that.

> In Julia functions are generic, and specialized to methods acting on arbitrary combinations of types; they are freed from the data.

...yes, just like in CLOS (unsurprisingly, given Julia's heritage), and those types are effectively CLOS classes.

Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @12:54PM (#26864985)
Well, it seems as if we were just at cross purposes due to terminology.

Although multiple dispatch in CL (and Perl) predates Julia, I was not aware that Julia’s design derived from it. Do you have a reference that traces this?

Re:Test for lists in Cython by jhgb on Monday April 19, 2021 @01:36PM (#26865631)
I find it virtually certain that it does derive from it. Considering that one of the authors of Julia wrote Julia's front-end in Lisp (https://github.com/JuliaLang/julia/blob/master/src/julia-par... and some other files in the same directory), it would have been astonishing for CLOS to not have major impact on the design. There's also some relevant statements in a paper on Julia's design (https://dl.acm.org/doi/10.1145/3276490) in the part on multiple dispatch in section 7. Related Work, where CLOS and its "algebraic cousin" Dylan are mentioned. I got the impression that Julia's object system is basically CLOS without quite a few of CLOS' complexities such as inheritance (which in CLOS necessitates some advanced extension facilities to cover some corner cases if method lookup doesn't do what you want it to do if you're attempting a highly complex application model). The nice effect of those feature removals was that in many cases monomorphization of call sites in emitted native code is possible, which is presumably the other reason for those feature removals: suddenly even primitive operations such as +, * etc. can be generics without incurring (most of the time) dispatch cost at runtime. That (primitive operations being generic functions) is not the case in CLOS, although that can also very well be attributed to backwards compatibility efforts in Common Lisp.

Interestingly enough, in Julia's documentation, the section "Noteworthy Differences from other Languages" (https://docs.julialang.org/en/v1/manual/noteworthy-differenc...) compares Julia to only several relevant languages, which are: Matlab, R, Python, C/C++, and...Common Lisp, of all things. I very strongly doubt that this is a coincidence.

Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @02:00PM (#26865985)
Thank you for that interesting reply.
Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @08:46AM (#26862113)
The standard way to make a histogram in Julia is histogram(data)

Using the latest version (1.6 - although 1.6.1 just came out) the time to first plot is just a few seconds. After that, plotting in the REPL is instantaneous.

I probably don’t understand what you’re getting at when you speak of making frequent changes to code. REPL-based development in Julia is excellent, and there are Pluto notebooks as well.

Re:Test for lists in Cython by Gravityloss on Monday April 19, 2021 @09:19AM (#26862413)
The way I would like to work is to have the repl open on the left hand side of the screen and code editor (like Sublime text, I'm sure many use Vim) on the right hand side.

I would run the code in repl (just using up-arrow and enter), get some plot, modify the code in the editor, save it, and rerun it repl.

Repl is used for connecting inputs to the program, not for editing. Often times you want to develop some small program that is part of a bigger program. So you run the big program up to the point it calls the small program. Or you run with some mock data. Then you have all your inputs for the small program, so you can start iterating it. Run - observe - edit - run - observe - edit.

In Matlab this worked because it detected if the file had changed, and reloaded it. You didn't specifically have to call load("my_function.m") before every call to it. This means you can just lift code from the big program and iterate on it in repl.

Re:Test for lists in Cython by rsfern on Monday April 19, 2021 @09:38AM (#26862606)
Check out Revise.jl, it enables this workflow, and it’s awesome.

https://docs.julialang.org/en/v1/manual/workflow-tips/#Revis...

Re:Test for lists in Cython by leephillips on Monday April 19, 2021 @09:46AM (#26862693)
Also, my Julia REPL is in a term buffer in vim, and I communicate with it (in both directions) from my editing buffer using the vim-sendtowindow plugin.