ChatGPT 与 Groovy 一行代码

作者: Paul King
发布时间: 2023-10-19 06:00PM


我问 ChatGPT 是否可以将一些简短的/一行代码的编程相关冷笑话表示为简短的/一行代码的 Groovy 脚本。它最初的回答有点令人失望,但在一些强制和一些“后期制作调整”之后,这篇文章包含了结果。请注意,双关语的质量参差不齐。

但在开始之前,Groovy 是与基于云的生成式 AI 系统交互的绝佳语言。您可以查看以下 GitHub 仓库,它展示了如何使用 Groovy 和 Micronaut 与 ChatGPT 交谈。这个例子反过来是基于 Ken Kousen 在 Java 中的类似示例。查看他关于该主题的精彩 视频。还可以查看 Guillaume Laforge 最近关于使用 Groovy 通过其 PaLM 2 API 与 Google 的 Bard 交谈以及使用 LangChain4J 的文章。

话虽如此,我们只是为这篇文章使用了 Web UI。现在,让我们看看一些 PUNch 行…​


问:为什么程序员总是把圣诞节 🎄 和万圣节 🎃 混淆?

答:因为 25 十进制 (Dec) 等于 31 八进制 (Oct)。

我们可以使用以下 Groovy 脚本进行验证

def christmas = 25 // dec
def halloween = 031 // oct
assert christmas == halloween

问:为什么 Groovy 是一种如此简洁的语言?

答:因为它借鉴了 Go 的一些特性,支持类似 R 的数据科学,但仪式感较低,混合了 Python 和 Perl 的剂量,借鉴了 Java 的一部分,并加入了 C# 的一些元素,最后还融合了一些 Ruby 的特性。

我们可以使用以下 Groovy 脚本进行验证

assert 'Groovy' == 'Go'.take(1) + 'R'.toLowerCase() +
                   'Python'['Perl'.size()] * 2 +
                   'Java'['C#'.size()] + 'Ruby'[-1]

问:为什么那个开发者破产了?

答:因为他的资金缓存、智能感知和空股票都空空如也 💰。

我们将 Expando 类与 Elvis 运算符和 Groovy 真值相结合来验证这个事实

def money = intelli = new Expando()
def rich = money.cache ?: intelli.cents ?: null?.stocks
assert !rich

问:为什么程序员认为使用 Groovy 很棒?

答:因为创建一盒字母排序的巧克力很简单。

我们创建了一个“可排序”的 Chocolate 记录,利用了默认参数和声明式增强。然后我们创建了一个 Box 类,它委托给 List。然后我们创建了一盒巧克力,并使用 toString() 方法检查它是否“字母排序”

@Sortable @ToString(ignoreNulls = true)
record Chocolate(int cocoa, String filling = null) {}

class Box { @Delegate List<Chocolate> contents }

var box = new Box(contents: [
    new Chocolate(80),
    new Chocolate(50, 'Caramel')
].sort())

assert box.toString() == '[Chocolate(50, Caramel), Chocolate(80)]'

如果生活给了你甜瓜,…​

…​你可能患有阅读障碍。 🍈🍋

让我们使用 Groovy 的灵活索引对单词“melons”进行一些重新排列,看看我们是否能得到“lemons”

def dyslexic = 'melons'[2..0,3..-1] == 'lemons'
assert dyslexic

6:30 是时钟上最好的时间,当之无愧。 🕡

让我们创建一个 6:30 的 LocalTime,并检查指针是否指向下方。分针在 60 分钟内移动 360 度,因此每分钟移动 6 度。我们可以检查 6:30 时,它是否指向正下方 (180°)。时针在 720 分钟(半天)内移动 360°,因此我们将总分钟数除以 2。总分钟数是小时数乘以 60 加上当前小时的分钟数。在 6:30,我们知道时针会移动到 6 和 7 之间的一半(15°),但为了测试,我们将确保它指向下方(我们将说它在直线下方 20° 内,我们将指定为一个范围)。以下是结果

def (h, m) = LocalTime.of(6, 30)[HOUR_OF_DAY, MINUTE_OF_HOUR]
assert 6 * m == 180L
assert (h * 60 + m).intdiv(2) in 180L..200L

问:无知和冷漠有什么区别?

答:我不知道,也不在乎。

为了用 Groovy 展示这一点,我们首先应该声明我们的无知和冷漠。然后我们计算差异,最后检查我们的断言

int ignorance, apathy
int know = care = ignorance - apathy
assert !know && !care

Groovy 能帮我回答这个问题吗:先有鸡还是先有蛋?

当然,运行这段脚本

def (first, second) = ['egg', 'chicken'].shuffled()
println "Which came first, the $first or the $second? The eternal debate!"

它实际上只是按两种不同的顺序提出问题,但我相信你明白我的意思。


问:为什么死亡、税收和不变性相似?

答:因为在生活和编程中,它们是唯一你无法改变的东西!

由于死亡和税收是确定的,我们应该将关于它们的引言存储在一个不可变的结构中。记录提供浅层不变性,对于这种情况非常有用。对于深层不变性,请考虑使用 @Immutable AST 转换,因此在这里,即使我们的引言存储在可变的 ArrayList 中,也无法更改它。以下是一个示例

record Quote(String text, String author, int year) { }
var q1 = new Quote('Perfection is immutable. But for things imperfect, change is the way to perfect them.', 'Owen Feltham', 1840)
var q2 = new Quote('Nothing is certain except death and taxes.', 'Benjamin Franklin', 1789)

@Immutable
class FavoriteQuotes { List<Quote> list }

var favorites = new FavoriteQuotes([q1, q2])

问:为什么钻石和狗是人类最好的朋友?

答:因为钻石是永恒的,狗是毛茸茸的永远! 💎 🐕

让我们使用特性来检查钻石和狗的最佳朋友

trait HasBestFriend {
    abstract String friend()
    boolean isBestFriend(String candidate) {
        friend() == candidate
    }
}

class Diamond implements HasBestFriend {
    String friend() { 'girl' }
}

class Dog implements HasBestFriend {
    String friend() { 'man' }
}

assert ['man', 'girl'].collect{
    [new Diamond().isBestFriend(it),
     new Dog().isBestFriend(it)]
} == [[false, true], [true, false]]

问:为什么 Land Rover 汽车与 Land Rover Explore 智能手机相处得如此融洽?

答:因为它们都知道“探索”新领域的重要性,无论是在越野还是在线!

谁知道汽车和智能手机之间有什么关系,但趋势似乎是公司想要涉足这两个领域。同样,如果你有两个表面上毫无关系的类,Groovy 的鸭子类型,或者在这种情况下是属性处理,可能会让你比你想象的更容易地将它们组合在一起。

import groovy.transform.*

record Smartphone(String make, String model, String color, int year) { }

record Car(String make, String model, String color, int year) { }

def s = new Smartphone('Landrover', 'Explore', 'Black', 2018)
def c = new Car(s.toMap())
assert c.toString() == 'Car[make=Landrover, model=Explore, color=Black, year=2018]'

问:为什么绝地武士对冲锋队员使用精神控制,当他们找不到失踪的机器人时?

答:因为,正如欧比旺所说,“这不是你要找的机器人。你实际上是在找你遗失的钥匙,你会在最后查看的地方找到它们!”

首先让我们看看 Groovy 如何帮助我们找到我们正在寻找的机器人。当有几个克隆体时,机器人是最难找到的。我们不会提到克隆人战争!

我们将创建一个机器人及其克隆体的随机列表,然后搜索我们想要的机器人

@AutoClone class Droid { String name }

def r2d2 = new Droid(name: 'R2-D2')
def c3po = new Droid(name: 'C-3PO')
def droids = [r2d2, c3po]
3.times {
    droids << r2d2.clone()
    droids << c3po.clone()
}
droids.shuffle()
droids.eachWithIndex { droid, index ->
    if (droid == r2d2) println "Droid $index is $r2d2.name"
    if (droid == c3po) println "Droid $index is $c3po.name"
}

如果我们不想输出找到机器人的索引,我们可以使用另一个表达式来表明我们想要的机器人已经找到了

assert droids.any{ it.is(r2d2) }
assert droids.any{ it.is(c3po) }

当然,欧比旺使用绝地武士的精神控制,我们可以使用一些 Groovy 元编程来展示这一点,在这种情况下,是一个类别类

class JediMindTrick {
    static boolean is(Droid d, Droid other) { false }
}

use(JediMindTrick) {
    assert !droids.any{ it.is(r2d2) }
    assert !droids.any{ it.is(c3po) }
}

问:海盗的宠物鹦鹉试图说“Pieces of 7”时发生了什么?

答:它得到了一个 ParrotyError!" 🦜

如这里所示

try {
    pet.say('Pieces of 7')
} catch(ParrotyError e) {
    var plank = e.stackTrace
    plank.walk()
}

问:为什么函数不再互相调用?

答:因为它们具有常量参数。

根据定义,纯函数始终对相同输入返回相同的结果。因此,对纯函数的一种可能的优化是为给定的输入值集缓存结果。Groovy 提供 @Memoized AST 转换来执行此操作(以及用于闭包的 .memoized() 方法调用)。

让我们编写一个 StringUtil 类,它有一个几乎是纯函数。bothCases 方法的返回值就其输入而言是纯函数。它返回一个包含输入字符串的小写和大写值的列表。它还会在每次调用时增加一个计数器;这只是为了让我们了解发生了什么。

class StringUtil {
    static int count = 0

    @Memoized
    static List<String> bothCases(String s) {
        count++
        [s.toLowerCase(), s.toUpperCase()]
    }
}

我们将 @Memoized 注解应用于 bothCases,这将启用自动缓存。该注解具有一些可选的注解属性,用于配置缓存行为,但我们将使用默认值。

我们可以看到,对于常量参数,'Foo' 在我们的案例中被调用了两次,没有必要在第二次调用时调用 bothCases 方法,因为我们可以使用上一次调用中缓存的值。

assert StringUtil.count == 0
assert StringUtil.bothCases('Foo') == ['foo', 'FOO']
assert StringUtil.count == 1
assert StringUtil.bothCases('Foo') == ['foo', 'FOO']
assert StringUtil.count == 1

二进制:它就像 1、10、11 一样简单

println "Binary: It's as easy as ${(1..3).collect{ Integer.toBinaryString(it) }.join(', ')}"

问:我在绵羊农场的第一天工作,被要求赶 37 只绵羊?

答:我说 40! 🐑 🐏

assert 40 == Math.round(37/10)*10

问:程序员编写了什么代码来庆祝 Groovy 的 20 周年? 🎂

答:一个 hip-hip 数组

String[] celebrate = ['hip', 'hip']