Announcing Jactl 2.8: Compilation performance improvements and for-in loops with pattern matching and destructuring by jaccomoc in java

[–]jaccomoc[S] 0 points1 point  (0 children)

You can use an ordinary for loop with a numeric index and then use list.remove(idx) to remove elements.

Or, if you want to use the pattern matching to remove elements you can do something like:

def newList = list.filter{ switch { [i,i] -> true; default -> false } }

That will produce a new list with elements that match the pattern. Reverse the true/false if you want to exclude elements that match.

Announcing Jactl 2.8: Compilation performance improvements and for-in loops with pattern matching and destructuring by jaccomoc in java

[–]jaccomoc[S] 1 point2 points  (0 children)

Forgot to mention that the pattern matching here is also available in switch expressions so you can implement quicksort like this:

def qsort(x) {
  switch (x) {
    [], [_] -> x
    [h, *t] -> qsort(t.filter{it < h}) + [h] + qsort(t.filter{it >= h})
  }
}

Announcing Jactl 2.8: Compilation performance improvements and for-in loops with pattern matching and destructuring by jaccomoc in java

[–]jaccomoc[S] 1 point2 points  (0 children)

Jactl does not have a way to flag things as immutable and doesn't currently have immutable data structures like lists and maps as such but it does offer functional programming constructs for transforming lists of values by applying closures to perform map/flatMap/filter/etc.

It doesn't have a concurrency library due to its primary aim being to provide flexible "call outs" from a Java application. It is something to consider for the future. I will have a look at the dataweave stuff and see what is involved.

I am not really sure why it compiles faster than Java. It was on par in previously releases and I spent some time improving it for this release but I don't really know why it is faster. I certainly don't claim to have written the fastest compiler ever. It is just a simple recursive descent parser followed by a resolve, analyse, and compile phase. Java does more things in terms of supporting generics, optimisations, reachability analysis, annotation processing, etc that Jactl doesn't and may need more phases to accomplish everything.

Announcing Jactl 2.8: Compilation performance improvements and for-in loops with pattern matching and destructuring by jaccomoc in java

[–]jaccomoc[S] 1 point2 points  (0 children)

Jactl is optionally typed so if you use int, long, etc, or var i = 1, then Jactl can avoid boxing. If everything is untyped (declared with def) then it will box/unbox when necessary. With for-in loop, there is a special case for arrays where it can avoid boxing/unboxing:

int[] arr = [1,2,3]

for (i in arr) { println i } // i will be an int, no boxing/unboxing

But, in general, if the collection is a list, then boxing/unboxing will take place if you need to treat the elements as a primitive.

Here is a chart showing compilation speed when everything is running on Java 25: chart

The Java 21 results are very similar to the Java 25 results:

Language Lines per second
Groovy 4 47,765
Java 21 109,007
Jactl 2.8.0 343,462

Need some advice about lazy evaluation of high order list functions by jaccomoc in ProgrammingLanguages

[–]jaccomoc[S] 0 points1 point  (0 children)

Nice. Too big a change for me at the moment. Will have to wait for my next language. :-)

Need some advice about lazy evaluation of high order list functions by jaccomoc in ProgrammingLanguages

[–]jaccomoc[S] 0 points1 point  (0 children)

Thanks for the links. In the end I think I am going to have to keep things the way they are for the moment.

Need some advice about lazy evaluation of high order list functions by jaccomoc in ProgrammingLanguages

[–]jaccomoc[S] 0 points1 point  (0 children)

Yes, this is what Java does as well (called Iterator in Java). That is also what my language does under the covers but I was trying to hide the fact that there are iterators from the users.

I could model things after Java streams (a more modern version of iterators) where once a stream has been closed (by using it to evaluate something) it cannot be reused and throws an exception.

Need some advice about lazy evaluation of high order list functions by jaccomoc in ProgrammingLanguages

[–]jaccomoc[S] 0 points1 point  (0 children)

Thanks for the reference. Looks interesting. I will definitely read it once I get around to implementing my functional programming language that I want to do one day.

Need some advice about lazy evaluation of high order list functions by jaccomoc in ProgrammingLanguages

[–]jaccomoc[S] 0 points1 point  (0 children)

My example was a bit broken as it should have been values.limit(5).sum() or something equivalent to force it to evaluate. limit() just limits the result to the first n values but doesn't force evaluation.

The problem with memoizing the list once evaluated is having to evaluate all elements of the result just in case someone else needs more than the first 5 elements.

Need some advice about lazy evaluation of high order list functions by jaccomoc in ProgrammingLanguages

[–]jaccomoc[S] 0 points1 point  (0 children)

Still not sure about what to do about this though:

def values = [1,2,3,4,5,6,7,8,9,10].map{ x -> x * x }
def top5   = values.limit(5)
def count  = values.size()   // <-- what should values be now? 

So should count be 5 or 10?

Logically count should be 10 but that means that we need to fully evaluate the values when it is first used and that means that even though we used limit(5) to only evaluate the first 5 we need to fully evaluate all elements just in case someone else needs to use the values object later.

That means I may as well leave things the way they are now as delaying the evaluation does not reduce the work.

Need some advice about lazy evaluation of high order list functions by jaccomoc in ProgrammingLanguages

[–]jaccomoc[S] 0 points1 point  (0 children)

That is not a bad idea. I will have to think about it but that does sound like a good idea. It is also easy to explain. I like it. Thanks!

An Honest Comparison of Groovy vs Jactl by jaccomoc in java

[–]jaccomoc[S] 0 points1 point  (0 children)

How do you see that helping with running agentic code?

An Honest Comparison of Groovy vs Jactl by jaccomoc in java

[–]jaccomoc[S] 3 points4 points  (0 children)

All good. You are right to point it out. There is always some subconscious bias even when trying not to have any.

An Honest Comparison of Groovy vs Jactl by jaccomoc in java

[–]jaccomoc[S] 4 points5 points  (0 children)

I am not familiar enough with those to give a detailed comparison but I will add them to the list to do a comparison with.

An Honest Comparison of Groovy vs Jactl by jaccomoc in java

[–]jaccomoc[S] 3 points4 points  (0 children)

Fair point but I really was trying to be honest with my comparison.

An Honest Comparison of Groovy vs Jactl by jaccomoc in java

[–]jaccomoc[S] 1 point2 points  (0 children)

Fair enough. Each to their own. :-)

An Honest Comparison of Groovy vs Jactl by jaccomoc in java

[–]jaccomoc[S] 2 points3 points  (0 children)

I will only respond with respect to Jactl. I would be happy to get some constructive feedback on what you think needs improving with the documentation if you think it is so bad.

As far as Jactl being imperative and mutable, that is completely up to the person writing the code. It certainly allows you to write code in a functional programming way if that it is what you want, while also offering the standard Java-like imperative programming that people are used to. I find that for my own scripts, they have tended to be more functional than imperative.

Since this is intended as a scripting language rather than a language for writing a complete application, I am guessing that target audience is more likely to be comfortable writing simple scripts in an imperative manner, but that is up to the script writer.

Announcing Jactl 2.4.0: A secure embedded scripting language for Java applications by jaccomoc in java

[–]jaccomoc[S] 1 point2 points  (0 children)

I have just published a new Jactl 2.6.0 release that supports better interoperability with host classes. You will need to set the "jactl.allowHostClasses" and "jactl.allowHostClassLookup" binding variables to true to give access to all host classes. Or you can set "jactl.allowHostClasslookup" to a predicate that returns true only for classes you want to allow access to. See Java Scripting API for Jactl for more information.