2

是否可以使用“for 循环”样式语法创建函数?如果是这样,那这种风格的函数会被称为什么?

例如 for 循环遵循以下语法:

for(i = 0; i < 10; i++)
{
    //do something
}

是否可以用任何语言创建自己的函数,例如,称为“myFunction”的函数可以这样调用:

myFunction(x; y; z)
{
   //do something
}

(注意函数输入的分号而不是逗号,然后是块包装器)

通常在编程语言中,您只能创建一个函数并像这样调用它:

myFunction(input1, input2, input2);

所以基本上我希望能够创建一个接受输入的函数,用分号和代码块分隔,就像 for 循环一样。这可能吗?这个叫什么?

编辑 - 澄清:我不想写一个运行循环的快捷函数。我正在寻找编写一个组合函数,从语法的角度来看,它看起来像一个 for 循环。但是,组成函数永远不会调用“for”或出于任何原因。

编辑-这可以在“编译器”级别实现吗?我了解 JavaScript 中最接近的内容如下(但它不像 for 那样干净):

myFunction(x, y, z, function()
{
    //do something
});
4

5 回答 5

3

好吧...正如您已经说过的:您可以创建自己的方法,但不能创建关键字。for是这样一个关键字,关键字不必遵守常规规则,哪些方法可以。

我能想到的最接近的事情是:

void MyForLoop<T>(Func<T> myInitialization, Func<T, bool> myCondition, Func<T, T> myIteration, Action<T> myBody)
{
   // Check the arguments for null's.
    T iterator = myInitialization();
    while(myCondition(iterator))
    {
         myBody(value);
         value = myIteration(value);
    }
}

你可以这样称呼它:

MyForLoop(() => 0, i => i < 10, i => i + 1, i => Console.WriteLine(i));
于 2013-05-01T15:04:10.557 回答
1

您正在寻找一种新的 DSL(领域特定语言)。Java、python、javascript 和其他语言确实在不同程度上对此提供了支持。DSL 有时可能涉及特殊语法,例如您希望对分号执行的操作,或者它可以像编写非常好的 API 的能力一样简单(想想 jQuery)。JavaScript 不支持自定义语法,但该语言非常富有表现力,并且很容易创建一个读起来像英语的 api。

话虽如此,您可以继续按照您想要的方式编写代码,然后通过某种解析器运行它并进行转换。你应该看看coffeescript的源代码。您基本上需要熟悉编写自己的语言、创建语法、将内容解析为语法树和翻译代码。

就像我说的,其他语言确实支持创建自己的语法/DSL。这里有一些资源:
- http://www.slideshare.net/Siddhi/creating-domain-specific-languages-in-python
- http://www.jetbrains.com/mps/

就我个人而言,我认为任何时候你有自定义的语法都会让从事该项目的新人感到非常困惑。但是,也许这对您正在做的事情是有意义的。

于 2013-09-29T03:26:03.793 回答
0

您希望该函数接受以分号分隔的输入,为什么不将您的输入连接成一个以分号分隔的字符串!如果这对您有意义,那么只需将所有输入放在一个数组中并在数组上执行 a .join(';')。或者只是传递数组本身,如果分号不是您的特定要求。

于 2013-10-01T11:21:21.697 回答
0

您在 c# 中寻求解决方案,如果 f# 中的某些内容(afaik 这些语言可以“一起”使用)也受到赞赏,那么我可以为您提供以下片段(请注意,分隔不是您希望的分号,但是带空格):

函数 yourLoop 接受三个参数,两个整数:lowerBound upperBound 和一个函数(具有更具体的 'a -> unit 类型的副作用):body 的含义是

yourLoop (lowerBound:int) upperBound body

具有相同的效果

for i in lowerBound..upperBound do
  body(i)

该函数如下所示:

let rec yourLoop (lowerBound:int) upperBound body =
  if (lowerBound >= upperBound) then body upperBound
  else
    body lowerBound
    yourLoop (lowerBound+1) upperBound body 

例如,让它成为某个方法的主体

let something i = printfn "%s%i" "do something with " i

然后申请

yourLoop 0 5 something

产量

do something with 0
do something with 1
do something with 2
do something with 3
do something with 4
do something with 5

同样,如果你想自上而下循环,那么你可以写

let rec yourInvertedLoop lowerBound upperBound body =
  if (lowerBound >= upperBound) then body lowerBound
  else
    body upperBound
    yourInvertedLoop (lowerBound) (upperBound-1) body

屈服

yourInvertedLoop 0 5 something

do something with 5
do something with 4
do something with 3
do something with 2
do something with 1
do something with 0

对于更通用的功能,请考虑

let rec yourLoopIncr lowerBound upperBound next body =
  if (next lowerBound >= upperBound) then body lowerBound
  else
    body lowerBound
    yourLoopIncr (next lowerBound) upperBound next body 

您可以在其中指定循环的迭代方式。例如,

yourLoopIncr 1 25 (fun x-> 2*x) something

会产生

do something with 1
do something with 2
do something with 4
do something with 8
do something with 16

备注:请注意,此解决方案仅适用于不返回值的主体。当然,您仍然可以在控制台上写东西或改变变量等。例如将代码

let mutable x = 0
let somethingElse n = x <- x+n 
yourLoop 0 10 somethingElse

将 x 设置为值 55。

于 2013-05-03T10:29:34.340 回答
0

您的确切语法在 JavaScript 中是不可能的,但您想要的意图是。您想要的与现代浏览器中forEach提供的非常相似。Array

function myLooper(iterations, callback) {
    for(var i = 0; i < iterations; ++i) {
        callback(i);
    }
}

myLooper(4, function(i) {
    console.log(i);
});

// outputs
// 0
// 1
// 2
// 3

这是上面的小提琴

并且由于您还使用 C# 标记了它,因此这里是 C# 版本:

void MyLooper(int iterations, Action<int> action) {
    for(int i = 0; i < iterations; ++i) {
        action.Invoke(i);
    }
 }

我现在手头没有 C# 环境,所以上面的内容可能不太正确。

于 2013-05-01T15:06:44.910 回答