Eu tinha feito tudo ser and para não criar complexidade mas acho que neste caso simplifica. Já que and pe keyword o que vocês recomendam no lugar? "combine"?
Resolvi seguindo a sugestão dos arrays. Acabei conseguindo resolver a gambiarra da sobrescrita do === no Symbol com uma versão que identifica se pode aplicar o overload ou não.
E matar uma das coisas mais legais de Ruby que é a sintaxe flexível? Se tirarem isso da linguagem vai ser quase tão difícil fazer Internal DSLs em Ruby quanto é em Java.
Acho que nest eponto você está certo. Não há problema em utilizar (), mesmo eu achando inútil.
Aí não
Utilizar blocos do…end de mais de uma linha é convenção de Ruby. Existem dois problemas:
1 - Quando se utiliza uma DSL não se está programado (pelo menos não naquele trecho específico) em Ruby, se programa em uma outra linguagem que é criada. Esta linguagem não tem nenhuma obrigação de seguir as convenções da sua host language, pelo contrário.
Não acho menos feio do que ter de colocar ‘{’ e ‘}’ onde naturalmente não seria obrigado. DSLs internas tem algumas restrições, não há como fugir disso.
As restrições (de sintaxe) da Internal DSL só existem quando a host language não é flexível o suficiente para que a DSL tenha uma sintaxe específica. Em Java escrever uma DSL Interna é um problema grande exatamente porque a linguagem não é flexível mas em Ruby não existe tanta limitação.
Minha opinião é que você acha ‘feio’ porque está lendo código Ruby e não lendo código na linguagem que ele foi escrito, que é uma linguagem parecida (por restrições técnicas) com Ruby mas diferente. Se você cria uma DSL que segue a convenção da host language você não tem uma DSL, tem uma API. Talvez tenha até uma Fluent Interface, depende do caso, mas não tem uma nova linguagem, continua preso a antiga.
(droga, tinha respondido isso ontem, mas deu crash no safari e eu perdi o texto todo…)
Eram justamente destas restrições que eu estava falando.
De resto concordo plenamente com você. É bem verdade que fui um pouco chato pq tenho aversão a blocos de várias linhas com ‘{ … }’. Você já deixou bem claro que não é obrigação usar sempre as convenções quando o objetivo é uma DSL; e eu concordo. Porém (na minha opinião), no seu caso não haveria problema algum em usar o do…end:
spec = create_spec do
[:id<10]and[:id>1]
end
Eu até prefiro assim. Não me expressei muito bem, mas no fundo o que eu queria dizer é apenas para ter preferência pela convenção (já que ela existe) nestes casos onde é o gosto pessoal que manda. Realmente, em uma DSL para expressões aritméticas ‘{ … }’ fica mais elegante.
ps.: Phillip, comparar com Java foi sacanagem demais. O abismo entre as convenções e a falta de flexibilidade é enorme (o que não vale para Ruby). Se eu fosse apelar nessa linha exagerando um pouco, não acho que DSL nenhuma justifica ter nomes de classe minúsculo: minha_classe.meuMetodoEstatico(). CamelCase para classes seria quase que uma convenção "inquebrável". Mas como eu não vou apelar mesmo…