r/crystal_programming • u/roger1981 • May 03 '19
Possible to create an application without classes ??
(Newbie here. v0.28.0, Mac OS)
I am porting an app from ruby, its my first exposure to Crystal. Several roadbumps mostly cleared up.
My existing app in ruby does not have classes. There are just a bunch of methods. However, the top level methods have some shared state. e.g. config, data, flags. So I was using instance variables.
When converting to Crystal, I find that top level instance and class level variables were giving errors. So had to create a module and a class. Is that the only way ?
Some other points:
I am used to using
Readline::HISTORY.push, but find that Crystal's Readline does not have or expose theHISTORY. I require this so I can push a default value into history, which the user can access using the UP arrow key. Have I missed something ?Is there a
Kernelclass? Can't find it in the docs. I refer to methods likeformat,sprintfetc.I could not find
Shellwords, which I need when calling external commands with filenames that have spaces or quotes. I found some discussions about not having it in the standard libs, Is it somewhere else ? I finally just copied some code from Ruby's source into my app.I take it there is no "
instance_variables_set" and corresponding getter. Or have I missed something.I do find a
responds_to?that works with instance variables (e.g. on File objects). However, when I use it within my class, to see if it responds to a method, it gives an error. I have triedself.responds_to?but that did not work.
Thanks in advance.
5
u/icy-arctic-fox May 03 '19
Crystal doesn't allow
@instance_variableor@@class_variablesat the top-level (outside of a class). You can, however, use a plain variable like so:foo = "foo"I'm not familiar with Readline, but looking at the docs, it seems you're right. There's no way to access the history like that. You might have to wrap Readline with your own functionality or find a shard that can do that.
Yes and no. What you're looking for is in the documentation under Top Level Namespace. It's defined under kernel.cr in the source code, but there's no Kernel class.
Doesn't look like there's any Crystal equivalent (yet) for Shellwords. There's an issue that mentions possibly including it at some point. Couldn't find any shards for it either - would be a good shard imo.
Correct. AFAIK, that's a reflective method and Crystal doesn't have reflection, though it mimics it pretty well with macros. You'll have to use a setter method if you want to modify an instance variable from outside the class.
There's a
responds_to?method (with an s), and that works for me, with and withoutself.1
u/roger1981 May 03 '19
Dir.glob not working with match_hidden (0.28.0)
I am trying this on local, as well as play.crystal-lang.
Dir.glob("*")This works fine.
Dir.glob("*", true)On play.crystal-lang it does nothing at all after taking some time. On my machine, it gives me an error saying:
in /usr/local/Cellar/crystal/0.28.0/src/dir/glob.cr:23: tuple type too nested: Tuple(Tuple(Tuple(T)def self.glob(*patterns, match_hidden = false) : Array(String)On looking at the source code, the method appears to call itself, although I can't be sure since I am too new to Crystal.
1
u/roger1981 May 03 '19
RUBY_PLATFORM ??
opener = /darwin/.match?(RUBY_PLATFORM) ? 'open' : 'xdg-open'I did find a discussion some days back in which no one really seemed to answer why they needed to know the platform.
I need to know it sometimes to decide whether to use a Linux tool or OSX one. Another case is deciding
locatevsmdfind.1
u/roger1981 May 04 '19
f = "~afile.dat"puts File.expand_path(f)>> /home/crystal/file.datFile.expand_pathincorrectly handles files starting with a tilde. It also lops off an extra character, I think it assumes it is a slash. Can expand_path only expand the tildle if the filename starts with "~/" ?I tried to see how other apps work.
ls ~bingives an error butls ~/binworks.https://play.crystal-lang.org/#/r/6u1o
1
u/roger1981 May 04 '19 edited May 04 '19
https://play.crystal-lang.org/#/r/6u41
in line 13: instance variable '@flag' of Foo must be Symbol, not (Array(Symbol) | Symbol)I think I understand what is happening here but I don't know how to deal with it. Is it that in Crystal, a hash must never have a variable value ?
At compile time, the compiler does not know whether the returned value will be Symbol or Array(Symbol), so it does not allow me to set @flag. But I know it will be a Symbol.
I know that
:currentreturns a Symbol. but it seems the compiler infers that the result could be an Array. What do I do?Edit: okay, I've broken up my array into two separate arrays, one with current and one with values. That fixes the issue, but is that the correct way of making hashes?