Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dependency on Ruby #1

Open
jameshfisher opened this issue Jun 29, 2011 · 9 comments
Open

Remove dependency on Ruby #1

jameshfisher opened this issue Jun 29, 2011 · 9 comments

Comments

@jameshfisher
Copy link

I haven't examined Orbit in detail, but one design decision that sticks out as strange is the dependency on Ruby.

Ruby and its associated tools are a big dependency to pull in for a trivial use. Ruby isn't installed by default on any distros I know of. That reason alone is enough for someone to not choose Orbit.

In any case, there's no justification. The reasons given in the wiki are

  • "it's on of the best language available to create good looking DSL's". A DSL is not what's required here, is it? It's just structured information. SSJS gets one fine with just a JSON file. Besides, these things don't really have to be "good looking," they have to get the job done.
  • "When the files are written in a complete language you have great flexibility and can take full advantage of Ruby". If we must write this stuff in a complete language, then we should rely on one that's guaranteed the user already has installed. The most obvious one is D, which already has a JSON package. Failing that and wanting a scripting language, Python is the safest choice, but will at least screw over Windows users, which is not a good thing.
  • "There's no need to create a parser for a new config/spec format". I definitely agree that the creation of Yet Another Plaintext Format is something to be avoided like the plague. If JSON is really unsatisfactory (and I doubt it), then there's the choice of XML for power or YAML for prettiness.
@jacob-carlborg
Copy link
Owner

I'll answer your comments below:

  1. Structured information is not enough, it needs if statement, functions and similar. If statements are basically required, functions are nice to have. The reason for this is that the packages need to work on multiple platforms, therefore if statements are really good for doing platform specific configurations.
  2. Yes the obvious one is D, but I think it will be too verbose. Dependencies won't be a problem, I've embedded Ruby in the application. I'm very careful when choosing what my software depends on.
  3. I think I've already answered this in number 1.

I will write more detail about the tools.

@jmacdonagh
Copy link

I've embedded Ruby in the application.

What does that mean? As a Windows user, can I grab the orb tool and get going without installing Ruby?

@jacob-carlborg
Copy link
Owner

Yes, when there is a pre-compiled binary available, which there currently isn't. But to compile Orbit you need to link to libruby.

@chadjoan
Copy link

Using Ruby for this still seems very odd to me. When I want to do D programming I want to use D, not Ruby. Even if it's slightly suboptimal, I'd rather be able to look at package specs and see the language that I should already be familiar with. If I want to write an orbfile or somesuch, and I have to do nontrivial things, the LAST thing I want to do is spend a day or two learning Ruby before I can get serious work done.

Do you have any examples demonstrating why D is severely disadvantaged at doing this? That is, code that looks ugly and can't be fixed due to D's limitations?

@jacob-carlborg
Copy link
Owner

Since there seem to be a lot of people who rather want to use D than Ruby I can see if I can do anything about it. But in general I think D is too verbose for this type of things. The nice thing about Ruby is that the syntax allows to write in both in a style that looks like a declaration language and in a regular style.

For example, this is how the orbspec looks like for my serialization library:

name "orange"
summary "Orange is a serialization library."
version "1.0.0"
files Dir["**"/"*.{d,conf,png,markdown,sh}"] << "Makefile"
libraries %w[orange]
build "dsss"

In D it would look something like this:

name = "orange";
summary = "Orange is a serialization library.";
version_ = "1.0.0";
files = glob(join("**", "*.{d,conf,png,markdown,sh}")) ~ "Makefile";
libraries = ["orange"];
build = "dsss";

If we then take a look at an example of some more advanced features it would look something like this:
Ruby:

before :build do
  # do something before building
end

D:

beforeBuild({
    // do something before building
});

@chadjoan
Copy link

Cool!

Honestly, the D code doesn't look that bad to me. Of course, I will happily use any procedural language as a declarative language when duty calls. It's just a bad idea to do that when non-programmer users or people without working build systems have to configure the declarations. D can be invoked as an interpreter though, and people using this will have D compilers, so it's no problem.

For the first example, I can deal with that. In fact, "glob" is easier to look up than... Dir[A/B]? Maybe replace version_ with ver.

I would suggest the following change to the second example:

void beforeBuild()
{
    // do something before building.
}

I assume the program using the orbfile pastes it into some context. This context could then have a statement like:

static if ( __traits(compiles,beforeBuild()))
{
    beforeBuild();
}

(Untested, of course.)

@jacob-carlborg
Copy link
Owner

This is also a problem, I'm not completely sure how to do a runtime "eval" with D as the language.

@chadjoan
Copy link

Why is eval needed?

I'll admit it can be handy, but there are many compiled languages that get by alright without it. D can at least do the same thing at compile-time.

So, where does it come up and why is it needed?

(I do hope for a day when we have dynamic linking down-pat. Then an "eval" function can be implemented by compiling the string it's passed and then linking against the result.)

@jmacdonagh
Copy link

@jacob-carlborg I was playing around with this the other day. I think I may have found a solution. It's a little messy, but it achieves what you want.

First, you write a handler script, orb-update.d or something, and stick that somewhere in the path. The code would look something like this:

import std.stdio;

static if (!__traits(compiles, {import orbspec;}))
{
    static assert(0, "Couldn't find \"orbspec.d\" or it wasn't valid D.");
}
else
{
    import orbspec;
}

void main()
{
    static if (!__traits(compiles, NAME))
    {
        writeln("You didn't define \"NAME\"");
    }
    else
    {
        writeln(NAME);
    }
}

Then, in the root of some project, you must define orbspec.d. It's code would be simple:

auto NAME = "My Project";

Then, from the command line, a user would change directory to the project's directory (that has orbspec.d), and enter the command orb-update.d. On Windows, .d can be associated with rdmd, and on Linux of course you can do the shebang notation.

Of course, that orb-build.d script above needs some work. For example, it eats all dmd errors that might occur when trying to import orbspec.d. All easily fixable. If a user updates orbspec.d, they simply have to run orb-update.d and rdmd will take care of the rest.

You can add in "optional" features that orb-update.d could support by doing static if statements as @chadjoan pointed out.

It's a little more verbose than Ruby, but it makes sense that Orbit should eat its own dog food. I think it's pretty nifty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants