#937 Suggestion: More convenient echo function

katox Tue 26 Jan 2010

After years of fiddling with bash scripts I really miss some trivial echo onliners. Let's say this common output:

status:

working...ok

Now:

echo("status:")
echo("")
Sys.out.print("working...")
echo("ok")

New:

echo("status:")
echo("")
Env.cur.out.print("working...")
echo("ok")

Using the patch below:

echo("status:")
echo
echo("working...", false)
echo("ok")

I know it is super trivial but I always write the last example first, try to compile or staring at errors and then writing it properly.

Suggested patch: echo.diff

brian Tue 26 Jan 2010

I don't particularly like using a boolean flag for echo (especially since I pretty rarely don't actually print a full line).

The way I handle this stuff is I just have a mixin with lots of conveniences I use when writing quick and dirty scripts.

katox Wed 27 Jan 2010

Long version: Actually it was meant to make fansh interaction more fluent and also to be able to replace short bash scripts with Fantom code - so it intentionally very similar to avoid mental excercises (going from echo to echo("") and Env.cur.out.print) while rewriting such scripts.

I agree that second boolean parameter is not ideal I only wanted something simple. Another option would be to use some kind of optional flags, for instance don't output extra newline character, escape special characters, output as code.

I understand you don't want to complicate echo functionality or even blow your Obj class but these additions are tiny though tremendously useful (including better clarity of such code snippets). I don't think people start hacking together a script by front-up writing mixins with various outputs.

Short version: The argument is the same as having echo at all - speeding up reading and writing of very common basic output constructs.

Another thing is slow (JVM) startup of fantom scripts but this could be alleviated by some kind of a deamon (like scala compilation daemon) - JVM ClassLoader per Pod will make it a real option.

brian Wed 27 Jan 2010

Do you use util::AbstractMain for your scripts? That is what I always use now a days. That might be a good place to stick convenience functions.

Yes - slow JVM startup sucks for scripts. Having a Nailgun like solution would be nice, or eventually even better just having a FanVM without all the overhead of the JVM.

andy Wed 27 Jan 2010

The argument is the same as having echo at all - speeding up reading and writing of very common basic output constructs.

I can see that angle - but we certainly don't want to duplicate all those somewhere outside of OutStream. So a better pattern would probably be:

out := Env.cur.out
out.printLine("status:")
out.printLine("")
out.print("working...")
out.printLine("ok")

Or even

out := Env.cur.out
out.print("status:

           working...")
out.printLine("ok")

A bit more verbose, but I think thats really want you want. I think Obj.echo needs to stick to what it is, just a quick and dirty way to dump a line to stdout.

katox Wed 27 Jan 2010

Do you use util::AbstractMain for your scripts?

I do in scripts, it is a great tool to avoid tedious task like parsing cmdline arguments. I don't in simple fansh try-out sessions where I nearly always bump into this. I tried to remove the echo limitation with no extra function while preserving backwards compatiblity.

I have really no intention to go farther than fixing inconveniences with echo. The last thing I'd like to see is Obj API blow up.

brian Wed 27 Jan 2010

how do you use Sys.out in the fansh?

things are dumped automatically:

fansh> "$Date.today $Time.now"
2010-01-27 10:17:13.046

katox Wed 27 Jan 2010

how do you use Sys.out in the fansh?

You got me ;), I forgot it behaves different as a single statement. But I can use it quite normally while trying out closures.

["a", "b", "d"].each { if ("b" == it) Sys.out.print(it); echo ("_${it.toStr}_") }

results in

_a_
b_b_
_d_

which is what'd expect. Also you can do

echo("AA"); f(); echo("BB"); g();

but obviously you can't write

"AA"; f(); "BB"; g()

If you try

Sys.out.print("AA"); Sys.out.print("BB")

you get

AABB

but for a single statement it also dumps out ref

Sys.out.print("AA")

yields

AAfan.sys.SysOutStream@273686

On the other hand echo has Void return type, no problem there.

echo("AA")

yields

AA

I know it is all pretty contrived - but I use echo variants in all sorts of debugging insane code (to be done properly later).

ivan Wed 27 Jan 2010

btw, for writing lots of info it also convenient to use with-blocks. Modified Andy's example:

Env.cur.out
{
  printLine("status:")
  printLine("")
  print("working...")
  printLine("ok")
}

jodastephen Wed 27 Jan 2010

Stupid, mad idea time...

What if a class could define a "default" method.

public class Out {
  default Void println(Str str) { ... }
  Void print(Str str) { ... }
}

Then, for any object of that type, calling on the object is a shorthand for calling that method:

out := Out()
out.println("hello")   // normal, as per Fantom today
out.print("hello")     // normal, as per Fantom today
out("hello")           // language change, calls the default method
// or possibly
out.("hello")          // alternate syntax

Then, the echo case is handled by a general purpose feature.

echo.print("working...")
echo("OK")                     // short for echo.println("OK")

(because the echo() method would return Env.cur.out.)

Well, I said it was a bit of a mad idea. (Problems with variable vs method namespaces and clash with constructor syntax amongst others)

But I think it might also apply to how a Func object can be invoked directly, so it seemed worth mentioning in case it kicks off any other ideas...

brian Wed 27 Jan 2010

I think in Scala, foo() is sugar for foo.apply(). That is how they do list/map indexing too - just using () as shortcut for apply.

In our case it would be call.

msl Thu 28 Jan 2010

It hadn't occurred to me that echo was a method on Obj. Seems like a bit of an ugly corruption of the object model for the sake of convenience (but hey, we all do that all the time).

Would something like this be easier managed through being able to import specific slots above just objects? Something like:

import sys::Env.cur.println as echo
class MyClass {
  Void main() {
    echo("Doing stuff")
  }
}

I guess there'd need to be some checking that what you're importing is available from a static context (ie Env.cur is static, so the handle you get to println() is accessed through that context) but it should be relatively doable, no?

mike Thu 28 Jan 2010

Having a Nailgun like solution would nice, or eventually even better just having a FanVM without all the overhead of the JVM.

Now there's an interesting idea. LLVM perhaps?

tactics Thu 28 Jan 2010

Now there's an interesting idea. LLVM perhaps?

Adding the LLVM compilation target

mike Thu 28 Jan 2010

@tactics: Thanks, I missed that thread. Obviously not something one could do in a weekend. Getting fan to run in embedded devices would be extremely cool though...

tactics Thu 28 Jan 2010

I don't know the progress MoOm has made, but I'm really excited for something like that too. It'd be sweet to be able to write Fantom wrappers for native C libraries.

mike Thu 28 Jan 2010

I think there would end up being far more work to do on the native C part than the FCode ==> LLVM translator.

Login or Signup to reply.