How to understand this syntax construction in Pharo Smalltalk? - smalltalk

What does this syntax { ...: ...} mean? Example:
Class {
#name : #TypExamples,
#superclass : #Object,
#category : #'Typer-Core-Examples-OLD'
}
{ #category : #accessing }
TypExamples >> recursion [
| x |
x := [ x ].
^ x
]
Is it a dictionary? I did not find such syntax in the Pharo Cheat Sheet. Is it legal for Playground and for methods body?

This is not Pharo syntax at all. It is "tonel" format, which is a code storing format.
It is composed by chunks of STON (Smalltalk Object Notation, sort of JSON for Pharo) and code itself.
And no, this is not "direct-to-playground" code, you need to use a tool to inject it (like Iceberg or Monticello).

And if you want to read a bit more about the Tonel file format, there is a specification. It was developed to enable better git support. Smalltalk has used different version control systems before, including the Monticello dvcs which made it slow in embracing git.

Related

Why is the perl6 repl not distinguishing between two different classes?

I'm trying to create some classes in the repl and when I create a second class with the same attributes as the first class I'm told it's already defined.
Is this a simply a problem with the repl not handling namespaces correctly? It works as expected in a file.
Perl6 version: This is Rakudo version 2018.10 built on MoarVM version 2018.10
implementing Perl 6.c.
> class Thing {
* has $.stuff;
* }
(Thing)
> class OtherThing {
* has $.stuff;
* }
Package 'OtherThing' already has an attribute named '$!stuff'
in any scope_declarator at /home/path/.rakudobrew/moar-2018.10 /install/share/nqp/lib/Perl6/Grammar.moarvm line 1
in any term:sym<scope_declarator> at /home/path/.rakudobrew/moar-2018.10/install/share/nqp/lib/Perl6/Grammar.moarvm line 1
in any term at /home/path/.rakudobrew/moar-2018.10/install/share/nqp/lib/Perl6/Grammar.moarvm line 1
I just tried to replicate this slightly differently on my REPL, I get no error...
> class Thing { has $.stuff }
(Thing)
> class OtherThing { has $.stuff }
(OtherThing)
>
PS. I do get the same error as you when spreading the blocks over multiple lines.
This is Rakudo Star version 2018.10 built on MoarVM version 2018.10 implementing Perl 6.c.
Looks like your error is introduced by the * multi-line block logic in the REPL - I think it is a bug. Please can you report it?

How do I invoke a Java method from perl6

use java::util::zip::CRC32:from<java>;
my $crc = CRC32.new();
for 'Hello, Java'.encode('utf-8') {
$crc.'method/update/(B)V'($_);
}
say $crc.getValue();
sadly, this does not work
Method 'method/update/(B)V' not found for invocant of class 'java.util.zip.CRC32'
This code is available at the following links. It is the only example I've been able to find
Rakudo Perl 6 on the JVM (slides)
Perl 6 Advent Calendar: Day 03 – Rakudo Perl 6 on the JVM
Final answer
Combining the code cleanups explained in the Your answer cleaned up section below with Pepe Schwarz's improvements mentioned in the Expectation alert section below we get:
use java::util::zip::CRC32:from<Java>;
my $crc = CRC32.new();
for 'Hello, Java'.encode('utf-8').list {
$crc.update($_);
}
say $crc.getValue();
Your answer cleaned up
use v6;
use java::util::zip::CRC32:from<Java>;
my $crc = CRC32.new();
for 'Hello, Java'.encode('utf-8').list { # Appended `.list`
$crc.'method/update/(I)V'($_);
}
say $crc.getValue();
One important changed bit is the appended .list.
The 'Hello, Java'.encode('utf-8') fragment returns an object, a utf8. That object returns just one value (itself) to the for statement. So the for iterates just once, passing the object to the code block with the update line in it.
Iterating just once could make sense if the update line was .'method/update/([B)V', which maps to a Java method that expects a buffer of 8 bit ints, which is essentially what a Perl 6 utf8 is. However, that would require some support Perl 6 code (presumably in the core compiler) to marshal (automagically convert) the Perl 6 utf8 into a Java buf[] and if that code ever existed/worked it sure isn't working when I test with the latest Rakudo.
But if one appends a judicious .list as shown above and changes the code block to match, things work out.
First, the .list results in the for statement iterating over a series of integers.
Second, like you, I called the Integer arg version of the Java method (.'method/update/(I)V') instead of the original buffer arg version and the code then worked correctly. (This means that the binary representation of the unsigned 8 bit integers returned from the Perl 6 utf8 object is either already exactly what the Java method expects or is automagically marshaled for you.)
Another required change is that the from<java> needs to be from<Java> per your comment below -- thanks.
Expectation alert
As of Jan 2015:
Merely using the JVM backend for Rakudo/NQP (i.e. running pure P6 code on a JVM) still needs more hardening before it can be officially declared ready for production use. (This is in addition to the all round hardening that the entire P6 ecosystem is expected to undergo this year.) The JVM backend will hopefully get there in 2015 -- it will hopefully be part of the initial official launch of Perl 6 being ready for production use this year -- but that's going to largely depend on demand and on there being more devs using it and contributing patches.
P6 code calling Java code is an additional project. Pepe Schwarz has made great progress in the last couple months in getting up to speed, learning the codebase and landing commits. He has already implemented the obviously nicer shortname calling shown at the start of this answer and completed a lot more of the marshaling logic for converting between P6 and Java types and is actively soliciting feedback and requests for specific improvements.
The code which is responsible for this area of Java interop is found in the class org.perl6.nqp.runtime.BootJavaInterop. It suggests that the overloaded methods are identified by the string method/<name>/<descriptor>. The descriptor is computed in function org.objectweb.asm.Type#getMethodDescriptor. That jar is available through maven from http://mvnrepository.com/artifact/asm/asm.
import java.util.zip.CRC32
import org.objectweb.asm.Type
object MethodSignatures {
def printSignature(cls: Class[_], method: String, params: Class[_]): Unit = {
val m = cls.getMethod(method, params)
val d = Type.getMethodDescriptor(m)
println(m)
println(s"\t$d")
}
def main(args: Array[String]) {
val cls = classOf[CRC32]
# see https://docs.oracle.com/javase/8/docs/api/java/util/zip/CRC32.html
val ab = classOf[Array[Byte]]
val i = classOf[Int]
printSignature(cls, "update", ab)
printSignature(cls, "update", i)
}
}
This prints
public void java.util.zip.CRC32.update(byte[])
([B)V
public void java.util.zip.CRC32.update(int)
(I)V
Since I want to call the update(int) variant of this overloaded method, the correct method invocation (on line 5 of the example program) is
$crc.'method/update/(I)V'($_);
This crashes with
This representation can not unbox to a native int
finally, for some reason I do not understand, changing the same line to
$crc.'method/update/(I)V'($_.Int);
fixes that and the example runs fine.
The final version of the code is
use v6;
use java::util::zip::CRC32:from<java>;
my $crc = CRC32.new();
for 'Hello, Java'.encode('utf-8') {
$crc.'method/update/(I)V'($_.Int);
}
say $crc.getValue();
I got this to work on Perl 6.c with following modification (Jan 4, 2018):
use v6;
use java::util::zip::CRC32:from<JavaRuntime>;
my $crc = CRC32.new();
for 'Hello, Java'.encode('utf-8').list {
$crc.update($_);
}
say $crc.getValue();
Resulting in:
% perl6-j --version
This is Rakudo version 2017.12-79-g6f36b02 built on JVM
implementing Perl 6.c.
% perl6-j crcjava.p6
1072431491

How to override equality method in Smalltalk?

I'm reading a book on Smalltalk and I have an exercise about the anomaly of disappearing element I'm not able to solve.
Object subclass: Book [
| isbn |
<comment: 'A book class'>
setIsbn: anIsbn [
isbn := anIsbn.
]
getIsbn [
^isbn.
]
= anotherBook [
^self getIsbn = anotherBook getIsbn.
]
]
| Library |
Library := Set new: 100.
Library add: (Book new setIsbn: '0-671-2-158-1').
(Library includes: (Book new setIsbn: '0-671-2-158-1')) printNl.
I read I have to override the hash method too, but I don't know how to do it. How do I amend the Book class in order to avoid the anomaly?
I can't really tell what are you asking about, but to override hash, you should do the same as with =, which you have overridden as well, just by including different definition. So you do something like:
hash [
"return hash here"
]
If you are asking what hash should be like… well think about it like that: objects that are equal have to have the same hash (but this doesn't have to work the other way around). So I'd suggest you to do something like
hash [
^ self getIsbn hash
]
Also about disappearing element. Set is a hashed collection. This means that before comparing it's element with the one you are looking for, it select's a subset by hash. So if you are not overriding hash it may select a subset that won't contain your desired element.
In the end I'd suggest you to use some different implementation of Smalltalk, because my head hurt when I was starting to learn it with gnu-smalltalk. Personaly I use pharo it provides a nice UI and allows you to see what you override, allows you to debug, etc.
There are a few further Smalltalk idiomatic issues with your code:
normally accessors in Smalltalk don't use get and set. So you'd have isbn: anIsbn and isbn.
you probably want to create an extra constructor that has the ISBN as a parameter so you don't have to send both new and the setter yourself:
Book>>onIsbn: anIsbn
^self new
isbn: anIsbn;
yourself
The basic rule is never override #= without overriding #hash

How do I do LISP (apply) in Dart?

The docs say to use f.call.apply(arguments), but that seems to only work for object methods, not functions.
testapply.dart:
#!/usr/bin/env dart
say(a, b, c) {
print("${a}!");
print("${b}!");
print("${c}!");
}
main() {
var args = [1, 2, 3];
say.call.apply(args);
}
Trace:
$ dart testapply.dart
'/Users/andrew/Desktop/testapply.dart': Error: line 11 pos 2: Unresolved identifier 'Function 'say': static.'
say.call.apply(args);
^
Is there a way to do LISP (apply f args) without using objects?
Alternatively, is there a way to dynamically wrap an arbitrary function in an object so that it can be applied using f.call.apply(arguments)?
Alternatively, can Dart curry?
The documentation page you refer to says,
This functionality is not yet implemented, but is specified as part of version 0.07 of the Dart Programming Language Specification. Hopefully it will find its way into our implementations in due course, though it may be quite a while.
That may or may not be the issue...

Writing a TemplateLanguage/VewEngine

Aside from getting any real work done, I have an itch. My itch is to write a view engine that closely mimics a template system from another language (Template Toolkit/Perl). This is one of those if I had time/do it to learn something new kind of projects.
I've spent time looking at CoCo/R and ANTLR, and honestly, it makes my brain hurt, but some of CoCo/R is sinking in. Unfortunately, most of the examples are about creating a compiler that reads source code, but none seem to cover how to create a processor for templates.
Yes, those are the same thing, but I can't wrap my head around how to define the language for templates where most of the source is the html, rather than actual code being parsed and run.
Are there any good beginner resources out there for this kind of thing? I've taken a ganer at Spark, which didn't appear to have the grammar in the repo.
Maybe that is overkill, and one could just test-replace template syntax with c# in the file and compile it. http://msdn.microsoft.com/en-us/magazine/cc136756.aspx#S2
If you were in my shoes and weren't a language creating expert, where would you start?
The Spark grammar is implemented with a kind-of-fluent domain specific language.
It's declared in a few layers. The rules which recognize the html syntax are declared in MarkupGrammar.cs - those are based on grammar rules copied directly from the xml spec.
The markup rules refer to a limited subset of csharp syntax rules declared in CodeGrammar.cs - those are a subset because Spark only needs to recognize enough csharp to adjust single-quotes around strings to double-quotes, match curley braces, etc.
The individual rules themselves are of type ParseAction<TValue> delegate which accept a Position and return a ParseResult. The ParseResult is a simple class which contains the TValue data item parsed by the action and a new Position instance which has been advanced past the content which produced the TValue.
That isn't very useful on it's own until you introduce a small number of operators, as described in Parsing expression grammar, which can combine single parse actions to build very detailed and robust expressions about the shape of different syntax constructs.
The technique of using a delegate as a parse action came from a Luke H's blog post Monadic Parser Combinators using C# 3.0. I also wrote a post about Creating a Domain Specific Language for Parsing.
It's also entirely possible, if you like, to reference the Spark.dll assembly and inherit a class from the base CharGrammar to create an entirely new grammar for a particular syntax. It's probably the quickest way to start experimenting with this technique, and an example of that can be found in CharGrammarTester.cs.
Step 1. Use regular expressions (regexp substitution) to split your input template string to a token list, for example, split
hel<b>lo[if foo]bar is [bar].[else]baz[end]world</b>!
to
write('hel<b>lo')
if('foo')
write('bar is')
substitute('bar')
write('.')
else()
write('baz')
end()
write('world</b>!')
Step 2. Convert your token list to a syntax tree:
* Sequence
** Write
*** ('hel<b>lo')
** If
*** ('foo')
*** Sequence
**** Write
***** ('bar is')
**** Substitute
***** ('bar')
**** Write
***** ('.')
*** Write
**** ('baz')
** Write
*** ('world</b>!')
class Instruction {
}
class Write : Instruction {
string text;
}
class Substitute : Instruction {
string varname;
}
class Sequence : Instruction {
Instruction[] items;
}
class If : Instruction {
string condition;
Instruction then;
Instruction else;
}
Step 3. Write a recursive function (called the interpreter), which can walk your tree and execute the instructions there.
Another, alternative approach (instead of steps 1--3) if your language supports eval() (such as Perl, Python, Ruby): use a regexp substitution to convert the template to an eval()-able string in the host language, and run eval() to instantiate the template.
There are sooo many thing to do. But it does work for on simple GET statement plus a test. That's a start.
http://github.com/claco/tt.net/
In the end, I already had too much time in ANTLR to give loudejs' method a go. I wanted to spend a little more time on the whole process rather than the parser/lexer. Maybe in version 2 I can have a go at the Spark way when my brain understands things a little more.
Vici Parser (formerly known as LazyParser.NET) is an open-source tokenizer/template parser/expression parser which can help you get started.
If it's not what you're looking for, then you may get some ideas by looking at the source code.