(Note: Put your mouse over the question to see any truncated portion. It will scroll left.)
On these last two, please consider the general spirit of the naming, not so the specific names used --which are completely fictitious.
l33t c0d3 $p1n!
include
and exclude
. While include
is the list of files to use, exclude
is list of files to exclude from the included list. Using exclude
makes it easier to specify a large selection and then subsequently omit a file or two. The include
list typically has a suitable default value, so a third parameter is sometimes also of use, append
, which concats to the defaults as opposed to replacing the include parameter outright.
Since these three parameters help define what is essentially one list of data, it would be nice if they could be specified as a single parameter too. So I gave the problem some thought.
Taking inspiration from the notion of a negated symbol (see facets/symbol/not). It occurred to me that any object that can be added or subtracted is taking part in the same "algebraic group" as whole numbers. And just as a whole number can be negative, why not also an array?
a = [:a,:b,:c,:d,:e]
n = -[:d,:e]
a + n #=> [:a,:b,:c]
So this could be very helpful. And it shouldn't be too much hard to implement.
class Array
def @-
@negative = !@negative
self
end
def negative?
@negative
end
alias :add :+
alias :sub :-
def +(other)
if negative?
if other.negative?
-add(other)
else
-sub(other)
end
else
if other.negative?
sub(other)
else
add(other)
end
end
end
...
end
I'm sure tighter implementation is possible, but you get the idea. So then include and exclude parameters could be specified in a single parameter.
files = [ '**/*', -[ 'Installedfiles' ] ]
Neat! But unfortunately it doesn't really solve the whole problem since YAML doesn't understand this negative listing concept either. It could still be of use in general Ruby scripts though. Notations such as this often prove very powerful. And in fact the idea does move us in a possible workable direction. There's no reason a string can't be marked as negative as well. After all it's just a flag. In fact, if we move the core method @- to Object itself, then any object can be so indicated. The above line could then be written:
files = [ '**/*', -'Installedfiles' ]
Methods such as Dir.multiglob(*files)
(another Facet) could use this extra bit of information to provide the desired results, equivalent to:
files = Dir.glob('**/*') - Dir.glob('InstalledFiles')
Of course, this still doesn't quite help us with the YAML configuration file, but with a little fudging we can get a useful format.
files: [ '**/*', '-InstalledFiles' ]
As for the append
parameter that was mentioned as the beginning, we could just add a special notation for this as well, say, '$' to mean defaults.
Okay. So will I use this bit of trickery to reduce three parameters to one? Perhaps. While the result is wonderfully practical in usage, it's not necessarily so simple to implement. Either a filter would have to split the one entry into three parts when loading, or an untold number of methods would have to augmented to take the trick into consideration. The later I imagine would simply prove too extensive w/o pre-established support for the negation concept. The former might be reasonable however. I'll give it a try.
In any case it was in interesting thought experiment. Although perhaps you have a better way to represent this kind of information?
module MyApp
class Project
module ToolSetA
module ToolSetB
class Project
module ProjectToolsets
module ToolSetA
module ToolSetB
class Project
module Toolsets
module ToolSetA
module ToolSetB
class Project
module PROJECT
module ToolSetA
module ToolSetB
module MYAPP
class Project
module PROJECT
module ToolSetA
module ToolSetB
class Something
def x
def y
mod_def a
mod_def x
class SomethingElse
Something.new
or subclassing would provide the instance methods x
and y
. Including however would provide the mod_def methods a
and x
instead along with adding SomethingElse to the including namespace. More refined means of controlling namespace become possible. For instance include_constants
could limit inclusion to constants only; vice-verse with include_methods
. Methods could be defined as both instance and module methods. And while we're at it, throw in a class_def
as an alternative to def self.x
.
class Module
def new
mod = self
Class.new{ include mod }.new
end
end