laurent.orseau
2021-10-11 08:12:13

“Instead, we recommend to use C arrays”


alexharsanyi
2021-10-11 10:58:44

I actually agree with the quote — when I started out using Racket, I wrote all my data structures using cons, car and cdr and this quickly became unmanageable. ActivityLog2 is still a Racket application today because I could use boring things such as structs and objects, there are still a few places where I use S-Expressions to hold data and those parts of the code base are the messiest and most fragile. My two cents.


markus.pfeiffer
2021-10-11 11:02:14

scheme teachers have been telling us since “forever” to not do that (produce this cons-car-cdr salad)


markus.pfeiffer
2021-10-11 11:02:38

inbetween we invented json and do the same thing just with dicts thrown in :shrug:


seanbunderwood
2021-10-11 12:55:09

I had the same experience as @alexharsanyi in school. Our professor taught us to use nested lists for everything and never bothered to teach us about creating interface functions, let alone using records. Most my classmates came out of the intro courses thinking that Scheme was an unwieldy mess and C was a comparative joy to use.


markus.pfeiffer
2021-10-11 13:12:43

I am starting to understand why my colleague, while a LISP fan, is writing code with lists of lists everywhere. It’s a mess.


markus.pfeiffer
2021-10-11 13:13:50

(when learning common lisp in my undergrad my tutors also were not helpful by (trying to) make Java look superior. but that’s another story…)


seanbunderwood
2021-10-11 13:51:41

I think that most the classic lisp books I’ve read do things that way until very late in the text. If they do introduce better ways of doing things, they don’t generally do a good job of motivating why you would want to use these other constructs.

My guess is it’s because the idea that you can use one simple structure - a cons cell - to build just about anything is more academically interesting. Or perhaps was in the 80s and 90s. Theoreticians tend to have an affinity for golden hammers.


markus.pfeiffer
2021-10-11 13:54:44

:laughing:


gmauer
2021-10-11 14:09:56

I’ll point out that many of the other languages are taking toe-in-the-water in the other direction. Usage of unstructured tuples and multiple returns is actually becoming more common in languages like c# and javascript and holding steadyish in python (though both namedtuples and dataclasses are great)


markus.pfeiffer
2021-10-11 14:35:31

rather concerning trend


seanbunderwood
2021-10-11 14:35:33

I also see a lot of resistance to that trend. I guess I can’t speak for JavaScript, but, at my last job, using tuples was all but banned.

In Python, the general consensus among people who worry about these things seems to be that, now that we have namedtuple, using regular tuples is only permissible in legacy code where you can’t change it without breaking too many consumers.


seanbunderwood
2021-10-11 14:36:46

(I’m not sure how well people who don’t worry about these things realize that, since the largest block of legacy code that uses unnamed tuples is the standard library.)


gmauer
2021-10-11 14:44:12

so to be clear, I think mostly its fine. In js for example - while there are some uses I arch my eyebrow at, the big one is standard functions like Object.entries() where it is pretty reasonable - labels wouldn’t really add any value to that. In C#, the implementation of value tuples is super weird and almost can’t be compared (there are unstructured tuples, but you can annotate a method so that the compiler is able to convert labels to indicies for you meaning no labels at run time). In python…I mean, yes, it can be bad, but also is largely used for stuff like dictionary iteration which again, you’re not really adding a ton of semantic usefullness with labels there


badkins
2021-10-11 14:49:51

I find lists handy. Sometimes, in cases where it’s very unlikely they will change, I’ll just use them directly. In other cases, I’ll hide them behind an interface, so the impact of a change is minimal.


massung
2021-10-11 15:10:56

It’s also important to call out the difference between “using a simple data structure to hold random stuff while prototyping and I don’t yet know entirely what I’ll need” and knowing the problem quite well and having the ability to go back and remove complexity by building structs, classes, or whatever is best.

Every time I’ve ever started by defining my data types, class hierarchies, etc. up-front, I’ve inevitably been wrong. And wrong in ways that cost me more time than if I had just started solving the problem first and then went back once I learned more about what I was actually solving instead of what I thought I was solving. :wink:


markus.pfeiffer
2021-10-11 15:15:57

I’d caution this with how quickly a “prototype” turns into something “in production”, at which point you really regret not putting the effort in naming tihngs at least :shrug:


markus.pfeiffer
2021-10-11 15:16:21

also try reading someone else’s code that only uses an amorphous list of stuff


seanbunderwood
2021-10-11 15:18:59

Well, and the thing I was criticizing was not the use of lists as a universal data structure. It’s the failure to teach the practical bits around how to use them in code that’s meant to last.


seanbunderwood
2021-10-11 15:23:32

If I remember right, Realm of Racket hits this very early on, while SICP and The Little Schemer don’t really touch on it very effectively.

Which is fine for what they are - they’re books that are more for computer scientists than working programmers - but, at the same time, I’m pretty happy to forgive people for reading a book that people widely tout as the be-all-end-all of lisp, and assuming that it’s the be-all-end-all of lisp.


massung
2021-10-11 15:30:14

Agreed. But - like everything in life - it’s a cautionary tale of choosing any extreme.


andreas.hofmeister
2021-10-11 15:41:13

@andreas.hofmeister has joined the channel


ryanc
2021-10-11 16:06:40

This discussion is really about types, and there are two ways that a language can treat types. (1) A type can mean a predicate on values in the language (possibly based on “type tags”). For example, in Racket there are strings and there are numbers and you can tell them apart with the string? and number? predicates, and you can talk about the “types” String and Number as meaning those sets of values. (2) A type can mean a distinct interpretation that you impose on some data. For example, the C double and intptr_t and int* types share all of the same “values” on my desktop (words of 64 bits), but the type controls what operations are available and in some cases how the operation is interpreted (eg, floating-point addition vs integer addition vs pointer addition). More generally, the meaning of a type can involve some combination of those two ideas. For example, the Java type ArrayList<String> is part predicate and part interpretation (the ArrayList class “tag” exists at run time; the String type parameter does not). I’ve been thinking about this because in ordinary Racket programming, we usually use struct to make new types-as-distinct-sets-of-values, but reasoning about macros requires thinking about the interpretations that macros impose on syntax that is just jumbles of atoms and pairs.


sw5355700
2021-10-11 16:10:52

The discussion really was about syntax and not data structures.


sw5355700
2021-10-11 16:19:47

It’s hard to tell from the quote because this person seems to be confusing syntax for data. (this is feature not a bug lol)


sw5355700
2021-10-11 16:24:44

Also it is true that once you start having lists of lists it becomes more difficult to manage the structures complexity naively and most people would use fmap or match in that case. But, that’s a much more advanced topic for dealing with list structured data that this person probably wasn’t aware of or considering.


markus.pfeiffer
2021-10-11 18:21:12

It’s quite a thing to assert what this discussion was really about :shrug:


ryanc
2021-10-11 21:43:19

Okay, fair, it’s not all the conversation is about. I tried to find a better opening line but I timed out before I found something I was happy with. Maybe just “Here is a generalization of one issue that I find interesting.”


chansey97
2021-10-12 06:19:12

“Nesting lists for everything” has an advantage over record or struct is that you can easily traverse mixed data structures. This is very useful for prototyping IMO. AFAIK Lisp or Racket’s struct has no feature something like auto deriving Functor, Foldable or Traversable.