1

我正在尝试编写一个进行类型转换的函数,这似乎是 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。另请参阅如何在 Rascal 中将值类型转换为 Map?

4

2 回答 2

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在此处(在地图内)或在链接的问题中使用 type 。处理可能有多种选择之一的情况的“标准” Rascal 方法是使用用户定义的数据类型和构造函数来定义这些情况。然后,您可以使用模式匹配来匹配构造函数,或者使用isandhas关键字来询问一个值,以分别检查它是使用特定构造函数创建的还是具有特定字段的。字段的规则是给定 ADT 的构造函数定义中所有出现的字段都具有相同的类型。因此,了解更多有关您的使用场景以查看此定义cast是否是最佳选择或者是否有更好的解决您的问题的方法可能会有所帮助。

已编辑

如果您正在阅读 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("<a href="http:\\/\\/blackberry.com\\/twitter" rel="nofollow">Twitter for BlackBerry\\u00ae<\\/a>"),
            "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("<a href="http:\\/\\/mobile.twitter.com" rel="nofollow">Mobile Web<\\/a>"),
            "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("<a href="http:\\/\\/itunes.apple.com\\/us\\/app\\/twitter\\/id409789998?mt=12" rel="nofollow">Twitter for Mac<\\/a>"),
            "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来提取您需要的信息。

于 2014-05-19T15:44:20.027 回答
0

该代码有一个错误。这是固定代码:

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

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

如果你发现你经常需要这种转换,那么你可能会避免使用 Rascal 的更好的部分,例如基于模式的调度。另请参阅 Mark Hills 的答案。

于 2014-05-20T08:54:11.453 回答