You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Elixir Phoenix的eex模板中正确使用with语句?

问题根源

你遇到的所有异常和不符合预期的表现都来自两个EEx和Elixir的基础特性:

  • EEx中<%= %>标签会将内部表达式的返回值转换为符合Phoenix.HTML.Safe协议的内容后渲染到页面,而<% %>标签仅执行代码,不会渲染返回值
  • 不带else分支的with语句如果模式匹配失败,会直接返回匹配失败的右值,不会执行do块内的代码
问题复现解释
  • 第一个测试用例你给with加了<%= %>,当day_data匹配失败时,with直接返回day_data的Map值,Phoenix.HTML.Safe默认没有实现Map类型的转换逻辑,因此抛出协议未实现错误
  • 第二个简化测试用例匹配:foo <- :bar失败,with返回:bar,被<%= %>转换为字符串bar渲染到页面,符合Elixir语法规则
  • 你尝试的带else分支的写法语法错误,是因为else后的分支逻辑属于with表达式的一部分,不能拆分到单独的<%= %>标签中,独立的->表达式不符合Elixir语法规则
正确写法

你完全可以在EEx模板中使用with语句,推荐两种合法写法:

写法1:不带=的with(最适配你的场景)

去掉with前的等号,with的返回值不会被渲染,仅当匹配成功时输出do块内的模板内容,匹配失败时无任何额外输出:

<% with [%{time: time}| _rest] <- day_data do %>
  <p><%= Timex.lformat!(time, "{WDshort}", Gettext.get_locale()) %></p>
<% end %>

你之前认为该写法不生效大概率是测试时匹配条件未命中,上述写法完全可以正常执行,匹配成功时会渲染p标签内容。

写法2:带=的with+合法else分支

如果需要渲染with的返回值,要补全合法的else分支,返回HTML安全的内容(比如空字符串、nil等),不要拆分else分支的语法结构:

<%= with [%{time: time}| _rest] <- day_data do %>
  <p><%= Timex.lformat!(time, "{WDshort}", Gettext.get_locale()) %></p>
<% else %>
  _ -> ""
<% end %>
写法对比

你当前使用的if match?写法也是完全合法的,适合单模式匹配的场景;with更适合多连续匹配的场景,可以避免多层嵌套的if判断,你可以根据实际业务场景选择即可。

内容的提问来源于stack exchange,提问作者Joe Eifert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 11:15:01