Live data from Hacker News

The Janet Language

janet-lang.org

191–200 of 203 posts

Re: The Janet Language

#191

Earlier quoted context omitted.

Thanks for clarifying, I did not find anything decisive searching persistent in combination with Clojure, weird. > Because "tuple" for an immutable sequence is rather specific to Python. As someone with a background in Swift, Rust and C#, all of which have the concept of a tuple, I did not make that connection, but thanks again.

> As someone with a background in Swift, Rust and C#, all of which have the concept of a tuple They all have tuples, but AFAIK in none of them is a tuple a sequence (well not sure about C# it might be there, but I'd be surprised). Usually a tuple is a form of lightweight, anonymous, structure, so it's addressed by field (even if the fields are positions), you usually can't iterate through tuples, or "index" them usin…

The .NET Tuple types Tuple and ValueTuple are not sequences — though the ITuple interface does enable item access by index without reflection — and ValueTuple instances are mutable, but .NET actually has two different immutable sequence types, ImmutableArray and ImmutableList, which are functionally similar but have different performance characteristics[1].

Along with the rest of the .NET immutable collection types[2], both are persistent data structures in the sense noted above.

In contrast, .NET tuple types are, as you say, lightweight, anonymous structures addressed by field. The ValueTuple types, in particular, are used in the underlying implementation of the C# tuple language feature[3].

AFAIK, Python has no built-in anonymous mutable structure types, though since type names in Python are basically only used for display purposes, you can easily create them at runtime, e.g.,

    def anon(**kwargs):
        class _:
            __slots__ = tuple(kwargs.keys())
    
            def __repr__(self):
                return 'anon(' \
                    + ', '.join((f'{i}={getattr(self, i)!r}' \
                                 for i in self.__slots__)) \
                    + ')'
    
            def __eq__(self, other):
                if not hasattr(other, '__slots__') \
                   or sorted(self.__slots__) \
                   != sorted(other.__slots__):
                    return False
                for i in self.__slots__:
                    if getattr(self, i) != getattr(other, i):
                        return False
                return True
            
        o = _()
        for k,v in kwargs.items():
            setattr(o, k, v)
        return o
    
Note that this differs in two notable ways from C# tuples:

1. Each object created has a unique type, so

    type(anon(x=1, y=2)) != type(anon(x=1, y=2))
More importantly, this means a distinct type object is created and stored for every call to anon, which could have significant performance implications at scale.

This could be easily fixed with a cache of already-created anonymous types (trading off slightly increased object-creation time, of course).

2. Equality in the above implementation is based on the equality of identically-named values rather than identically positioned values; in C#, we have

    (x: 1, y: 2) != (y: 2, x: 1)
and

    (x: 1, y: 2) == (y: 1, x: 2),
while in my implementation,

    anon(x=1, y=2) == anon(y=2, x=1)
and

    anon(x=1, y=2) != anon(y=1, x=2).
This was by choice, as it seems more intuitive; C# behavior is no more difficult to implement.

For read-only anonymous structure types, the Python standard library has namedtuple[4] (which, incidentally, bases value equality on position, not attribute name, so C#'s behavior is arguably more "Pythonic" than my own).

[1] https://learn.microsoft.com/en-us/dotnet/api/system.collecti...

[2] https://learn.microsoft.com/en-us/dotnet/api/system.collecti...

[3] https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...

[4] https://docs.python.org/3/library/collections.html#collectio...

Re: The Janet Language

#192
post #100

Earlier quoted context omitted.

They’re often called “hash sets” or “hash maps” in other languages - they are called this for a reason, and certainly not because they could be implemented as a list. std::map is not a good example anyway, you want to consider std::unordered_map for a more appropriate comparison. C++ is weird that way. (What C++ calls a map is not what most languages call a map. std::map doesn’t even satisfy O(1). You’d be surprised…

You said "requires" hashing. Sets and Maps do not require hashing. Through it is correct to observe the unfortunate naming convention in the c++ std lib. std::set and std::map should be std::ordered_set and std::ordered_map sts::unordered_set and std::unordered_map should be std::hash_set and std::hash_map If this were so then it might make the incorrect usage of these two options less prevalent. But they are both ma…

You interpreted my reply as “all sets and maps require hashing“ instead of “sets and maps are examples of data structures that can require hashing”… which they are.

Imagine someone says, every fruit in the world is sour, and someone answers, no there are plenty of fruits that are sweet, such as apples, and then an entire thread gets launched in an irrelevant direction pointing out that actually some apples are sour, which has no bearing on the original point.

Re: The Janet Language

#193

Earlier quoted context omitted.

Same reaction here... wow that is a rough looking language. Then again I always disliked those kinds of languages like Clojure. The syntax is just too much for me. I feel like if I used it, it would atrophy my skills in other more traditional languages.

I've been using Lisp for hobby projects for a few years. Yes the syntax takes some time, but > I feel like if I used it, it would atrophy my skills in other more traditional languages. was not the case for me at all. If you go into a text editor and remove all the parentheses, I find that's how Lisp programmers tend to see Lisp, (function argument) isn't that far from function(argument). Learning Lisp has only improv…

Reading Peter Norvig's PAIP (https://github.com/norvig/paip-lisp) in 1998 totally blew my mind. It completely changed how I think about programming in every other language I use(d). I love it still, and always will. And yes, my experience is the same as yours: learning lisp made me a better programmer in every other language I use (especially -- but not only -- Python).

The simplicity and symmetry of the syntax is a big part of that love for me. Being able to manipulate lisp code as lisp data, using the full power of the language to do so, is just brilliant.

Janet looks lovely! Looking forward to the book.

Re: The Janet Language

#194
post #170

Earlier quoted context omitted.

How'd you go about multiple-value-bind? Same problem with handler-case. When used interactively, Python also has _ to store the previous value (but Python only ever really returns single value, which is sometimes a tuple or a list that can be deconstructed into variables, iirc in CL if you don't request other return values, they are gone.) More generally, you'd want more of xargs-like functionality (eg. split result…

> Java-like languages don't immediately support something like that, but Shell-like do with redirection syntax, tee, xargs. But in Lisp you are not bound to the language syntax of Java. You can inside the language write tools to process forms. That's one of the main differences between Java and Lisp. Lisp has reader macros (to change the surface syntax of s-expressions) and macros to change the expression syntax. Tha…

I've been using CL and SLIME for over 10 years and had no idea about special meaning of "/"... TIL.

Anyways, the problem with handler-case still stands, as well as the other aspects s.a. chunked output, tee and redirects. It's something that would have to be programmed on top of the existing stuff, which was my point originally.

Re: The Janet Language

#195

Earlier quoted context omitted.

I went there, saw the Lisp syntax, and noped back out.

Same reaction here... wow that is a rough looking language. Then again I always disliked those kinds of languages like Clojure. The syntax is just too much for me. I feel like if I used it, it would atrophy my skills in other more traditional languages.

> I feel like if I used it, it would atrophy my skills in other more traditional languages.

If your skills in other languages are tied to a syntax then you never had any skills to begin with. I've used pretty much every syntax (and too many languages) out there and the only difference I've ever found is that ML syntax is nicer for automatically curried functions and LISP syntax is much nicer for meta-programming. The rest is effectively all down to paradigms, runtimes and libraries.

Re: The Janet Language

#196
post #134
post #70

Earlier quoted context omitted.

It's notable that raku (previously known as perl6) lets you write things in either direction, if I remember correctly something like @source >>> map { ... } >>> grep { ... } >>> my @sink; though note I'm typing from memory on my second coffee so I may have got that slightly wrong. Plus of course there's many languages with a |> operator so you can do g(x) |> f I also (the example is specialised for I/O but the implem…

Raku also has map and grep methods for collections, so it could be written as... my @sink = @source.map({...}).grep({...}).sort; Which also makes multithreading the operation easy: my @sink = @source.hyper.map({...}).grep({...}).sort.list; That said, I think the operator you're looking for is the feed operator, ==>: my @sink; @source ==> map {...} ==> grep {...} ==> sort ==> @sink; It also has the corresponding rever…

> That said, I think the operator you're looking for is the feed operator, ==>

Yes, yes it was.

Your clarifications, corrections and elaborations are much appreciated.

Re: The Janet Language

#198

Earlier quoted context omitted.

> Just pretend everything is a function call D uses Universal Function Call Syntax, where: f(a) g(f(a)) can be written as: a.f a.f.g It's a very popular feature.

Scheme has a shorthand for (cons a b) that's just (a . b), and (cons a (cons b c)) as (a b . c) Racket, a scheme-based language, extended the syntax so that any symbol appearing between two periods and not at the end of a list gets moved to the head of the list, so (a . b . c) becomes (b a c), which some people use so that (a . + . b) becomes (+ a b). The D syntax you describe is what schemes call the "threading macr…

I believe the general consensus is that the double dot notation might not have been the best idea.

FWIW it's mostly used for inequalities like `(a . But `<=` allows more arguments as in `(<= a b c d)` and here the double dot notation can't be used.

Re: The Janet Language

#199
post #172

Oh hey! Nice to see this on the front page here. I love Janet -- I've been using it for about year and a half, and it's now my go-to scripting language when I need something more powerful than bash, or when I want to hack on goofy little side project (some examples in my profile). Parsing expression grammars (think, like, declarative parser combinators?) are a really great feature for ad-hoc text parsing -- and nicer…

Is there somewhere I can keep up to date with books progress?

[deleted]

Re: The Janet Language

#200
post #172

Earlier quoted context omitted.

Is there somewhere I can keep up to date with books progress?

I'll announce it on my RSS feed/newsletter/twitter once it's done, if you use any of those. I'd estimate that it'll be out by the end of March; I won't write any public updates until it's ready for people to read.

Look forward to it.
Post reply on HN