写一个函数来做类型转换

时间:2014-05-19 12:05:00

标签: rascal

我试图编写一个执行类型转换的函数,这似乎是Rascal代码中经常出现的活动。但我似乎无法做到这一点。以下几种变体都失败了。

public &T cast(type[&T] tp, value v) throws str {
    if (tp tv := v)
        return tv;
    else
        throw "cast failed";
}

有人能帮助我吗?

更多信息:我经常使用模式匹配格式" Type Var" (即针对变量声明)以告诉Rascal表达式具有某种类型,例如

map[str,value] m := myexp

这通常是在我知道myexp具有类型map [str,value]的情况下,但省略匹配会使Rascal的类型检查机制抱怨。 为了防止错误,我通常将匹配的构造包装在if-then-else中,如果匹配失败则引发异常:

if (map[str,value] m := myexp) {
  // use m
} else {
  throw "cast failed";
}

我想使用一个通常完成工作的单个函数来缩短所有类似的代码片段,以便我可以编写代码

cast(#map[str,value], myexp)

PS。另请参阅How to cast a value type to Map in Rascal?

2 个答案:

答案 0 :(得分:1)

如果您确实需要这样做,最好的方法是:

public map[str,value] cast(map[str,value] v) = v;
public default map[str,value] cast(value v) { throw "cast failed!"; }

然后你可以说

m = cast(myexp);

它会做你想做的事情 - 实际的模式匹配被移动到cast的函数签名中,具有特定于你想要使用的类型的案例和处理所有事情的案例否则不匹配。

但是,我仍然不确定你为什么在这里(在地图内)或链接问题中使用类型value。处理可能有多种选择之一的情况的“标准”Rascal方法是使用用户定义的数据类型和构造函数来定义它们。然后,您可以使用模式匹配来匹配构造函数,或使用ishas关键字来查询值以检查它是使用特定构造函数创建的,还是具有特定字段,分别。字段规则是给定ADT的构造函数定义中所有出现的字段都具有相同的类型。因此,了解有关您的使用方案的更多信息可能有助于了解cast的此定义是否是最佳选择,或者是否有更好的解决方案来解决您的问题。

<强> EDITED

如果您正在阅读JSON,另一种方法是使用JSON语法和AST,它们也存在于库的那一部分(我认为您使用的那个更像是一个流阅读器,就像我们当前的那样文本读者和作者,但我需要更多地查看代码)。然后你可以做这样的事情(包含长输出以了解结果):

rascal>import lang::json::\syntax::JSON;
ok

rascal>import lang::json::ast::JSON;
ok

rascal>import lang::json::ast::Implode;
ok

ascal>js = buildAST(parse(#JSONText, |project://rascal/src/org/rascalmpl/library/lang/json/examples/twitter01.json|));
Value: object((
    "since_id":integer(0),
    "refresh_url":string("?since_id=202744362520678400&q=amsterdam&lang=en"),
    "page":integer(1),
    "since_id_str":string("0"),
    "completed_in":float(0.058),
    "results_per_page":integer(25),
    "next_page":string("?page=2&max_id=202744362520678400&q=amsterdam&lang=en&rpp=25"),
    "max_id_str":string("202744362520678400"),
    "query":string("amsterdam"),
    "max_id":integer(202744362520678400),
    "results":array([
        object((
            "from_user":string("adekamel"),
            "profile_image_url_https":string("https:\\/\\/si0.twimg.com\\/profile_images\\/2206104506\\/339515338_normal.jpg"),
            "in_reply_to_status_id_str":string("202730522013728768"),
            "to_user_id":integer(215350297),
            "from_user_id_str":string("366868475"),
            "geo":null(),
            "in_reply_to_status_id":integer(202730522013728768),
            "profile_image_url":string("http:\\/\\/a0.twimg.com\\/profile_images\\/2206104506\\/339515338_normal.jpg"),
            "to_user_id_str":string("215350297"),
            "from_user_name":string("nurul amalya \\u1d54\\u1d25\\u1d54"),
            "created_at":string("Wed, 16 May 2012 12:56:37 +0000"),
            "id_str":string("202744362520678400"),
            "text":string("@Donnalita122 @NaishahS @fatihahmS @oishiihotchoc @yummy_DDG @zaimar93 @syedames I\'m here at Amsterdam :O"),
            "to_user":string("Donnalita122"),
            "metadata":object(("result_type":string("recent"))),
            "iso_language_code":string("en"),
            "from_user_id":integer(366868475),
            "source":string("&lt;a href=&quot;http:\\/\\/blackberry.com\\/twitter&quot; rel=&quot;nofollow&quot;&gt;Twitter for BlackBerry\\u00ae&lt;\\/a&gt;"),
            "id":integer(202744362520678400),
            "to_user_name":string("Rahmadini Hairuddin")
          )),
        object((
            "from_user":string("kelashby"),
            "profile_image_url_https":string("https:\\/\\/si0.twimg.com\\/profile_images\\/1861086809\\/me_beach_normal.JPG"),
            "to_user_id":integer(0),
            "from_user_id_str":string("291446599"),
            "geo":null(),
            "profile_image_url":string("http:\\/\\/a0.twimg.com\\/profile_images\\/1861086809\\/me_beach_normal.JPG"),
            "to_user_id_str":string("0"),
            "from_user_name":string("Kelly Ashby"),
            "created_at":string("Wed, 16 May 2012 12:56:25 +0000"),
            "id_str":string("202744310872018945"),
            "text":string("45 days til freedom! Cannot wait! After Paris: London, maybe Amsterdam, then southern France, then CANADA!!!!"),
            "to_user":null(),
            "metadata":object(("result_type":string("recent"))),
            "iso_language_code":string("en"),
            "from_user_id":integer(291446599),
            "source":string("&lt;a href=&quot;http:\\/\\/mobile.twitter.com&quot; rel=&quot;nofollow&quot;&gt;Mobile Web&lt;\\/a&gt;"),
            "id":integer(202744310872018945),
            "to_user_name":null()
          )),
        object((
            "from_user":string("johantolsma"),
            "profile_image_url_https":string("https:\\/\\/si0.twimg.com\\/profile_images\\/1961917557\\/image_normal.jpg"),
            "to_user_id":integer(0),
            "from_user_id_str":string("23632499"),
            "geo":null(),
            "profile_image_url":string("http:\\/\\/a0.twimg.com\\/profile_images\\/1961917557\\/image_normal.jpg"),
            "to_user_id_str":string("0"),
            "from_user_name":string("Johan Tolsma"),
            "created_at":string("Wed, 16 May 2012 12:56:16 +0000"),
            "id_str":string("202744274050236416"),
            "text":string("RT @agerolemou: Office space for freelancers in Amsterdam http:\\/\\/t.co\\/6VfHuLeK"),
            "to_user":null(),
            "metadata":object(("result_type":string("recent"))),
            "iso_language_code":string("en"),
            "from_user_id":integer(23632499),
            "source":string("&lt;a href=&quot;http:\\/\\/itunes.apple.com\\/us\\/app\\/twitter\\/id409789998?mt=12&quot; rel=&quot;nofollow&quot;&gt;Twitter for Mac&lt;\\/a&gt;"),
            "id":integer(202744274050236416),
            "to_user_name":null()
          )),
        object((
            "from_user":string("hellosophieg"),
            "profile_image_url_https":string("https:\\/\\/si0.twimg.com\\/profile_images\\/2213055219\\/image_normal.jpg"),
            "to_user_id":integer(0),
            "from_user_id_str":string("41153106"),
            "geo":null(),
            "profile_image_url":string("http:\\/\\/a0.twimg.com\\/profile_images\\/2213055219\\/image_normal.jp...

rascal>js is object;
bool: true

rascal>js.members<0>;
set[str]: {"since_id","refresh_url","page","since_id_str","completed_in","results_per_page","next_page","max_id_str","query","max_id","results"}

rascal>js.members["results_per_page"];
Value: integer(25)

然后,您可以对lang::json::ast::json中定义的类型使用模式匹配来提取所需的信息。

答案 1 :(得分:0)

代码有错误。这是固定代码:

public &T cast(type[&T] tp, value v) throws str {
    if (&T tv := v)
        return tv;
    else
        throw "cast failed";
}

请注意,我们不希望将其包含在标准库中。相反,我们收集我们需要它的情况,并找出如何以另一种方式解决它。

如果您发现经常需要这种投射,那么您可能会避开Rascal的更好部分,例如基于模式的调度。另请参阅Mark Hills的答案。